]> arthur.barton.de Git - netatalk.git/commitdiff
Disable continous service feature by default, new option keepsessions to enable it.
authorFrank Lahm <franklahm@googlemail.com>
Wed, 27 Jul 2011 09:27:59 +0000 (11:27 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Wed, 27 Jul 2011 09:27:59 +0000 (11:27 +0200)
Fix a possible race condition between SIGCHLD handler and new connection attempts.

NEWS
etc/afpd/afp_options.c
etc/afpd/main.c
include/atalk/globals.h

diff --git a/NEWS b/NEWS
index 10e38c49372072e229bd8320d5f4f757b6670c14..44462cad43f5d701573a3b78faa43e9cf6dd02c2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,11 +1,15 @@
 Changes in 2.2.1
 ================
 
+* NEW: afpd: disable continous service feature by default, new option
+       -keepsessions to enable it
 * FIX: afpd: increase BerkeleyDB locks and lockobjs
 * FIX: afpd: create special folder as root
 * FIX: afpd: fix compilation error if --enable-ddp is used
 * FIX: afpd: More robust IPC reconnect error handling
 * FIX: afpd: ACL access checking
+* FIX: afpd: fix a possible race condition between SIGCHLD handler and
+       new connection attempts
 * FIX: cnid_dbd: increase BerkeleyDB locks and lockobjs
 * FIX: cnid_dbd: implement -d option, deletes CNID db
 * FIX: suse: initscript return better status
index b79bc8d1f443329bb220f5dbbf408e60e1e390b2..22ab58d6446d041bbcae353b59f4e311b4423f45 100644 (file)
@@ -240,6 +240,10 @@ int afp_options_parseline(char *buf, struct afp_options *options)
         options->flags |= OPTION_ANNOUNCESSH;
     if (strstr(buf, " -noacl2maccess"))
         options->flags &= ~OPTION_ACL2MACCESS;
+    if (strstr(buf, " -keepsessions")) {
+        default_options.flags |= OPTION_KEEPSESSIONS;
+        options->flags |= OPTION_KEEPSESSIONS;
+    }
 
     /* passwd bits */
     if (strstr(buf, " -nosavepassword"))
index 06f3ee168967cff731e20debefb6f7f1cb72c561..8c3f43ad6fe03826356c5df894102f9907944499 100644 (file)
@@ -52,11 +52,11 @@ static char **argv = NULL;
 #endif /* TRU64 */
 
 unsigned char  nologin = 0;
-
 struct afp_options default_options;
 static AFPConfig *configs;
 static server_child *server_children;
 static sig_atomic_t reloadconfig = 0;
+static sig_atomic_t gotsigchld = 0;
 
 /* Two pointers to dynamic allocated arrays which store pollfds and associated data */
 static struct pollfd *fdset;
@@ -94,7 +94,11 @@ static void fd_set_listening_sockets(void)
             continue;
         fdset_add_fd(&fdset, &polldata, &fdset_used, &fdset_size, config->fd, LISTEN_FD, config);
     }
-    fdset_add_fd(&fdset, &polldata, &fdset_used, &fdset_size, disasociated_ipc_fd, DISASOCIATED_IPC_FD, NULL);
+
+    if (default_options.flags & OPTION_KEEPSESSIONS) {
+        LOG(log_note, logtype_afpd, "Activating continous service");
+        fdset_add_fd(&fdset, &polldata, &fdset_used, &fdset_size, disasociated_ipc_fd, DISASOCIATED_IPC_FD, NULL);
+    }
 }
  
 static void fd_reset_listening_sockets(void)
@@ -106,7 +110,9 @@ static void fd_reset_listening_sockets(void)
             continue;
         fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, config->fd);
     }
-    fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, disasociated_ipc_fd);
+
+    if (default_options.flags & OPTION_KEEPSESSIONS)
+        fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, disasociated_ipc_fd);
 }
 
 /* ------------------ */
@@ -127,7 +133,12 @@ static void afp_goaway(int sig)
             LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGTERM");
             break;
         case SIGQUIT:
-            LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGQUIT, NOT disconnecting clients");
+            if (default_options.flags & OPTION_KEEPSESSIONS) {
+                LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGQUIT, NOT disconnecting clients");
+            } else {
+                LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGQUIT");
+                sig = SIGTERM;
+            }
             break;
         }
         if (server_children)
@@ -154,13 +165,18 @@ static void afp_goaway(int sig)
         reloadconfig = 1;
         break;
 
+    case SIGCHLD:
+        /* w/ a configuration file, we can force a re-read if we want */
+        gotsigchld = 1;
+        break;
+
     default :
         LOG(log_error, logtype_afpd, "afp_goaway: bad signal" );
     }
     return;
 }
 
-static void child_handler(int sig _U_)
+static void child_handler(void)
 {
     int fd;
     int status, i;
@@ -273,7 +289,8 @@ int main(int ac, char **av)
     }
 #endif
     
-    sv.sa_handler = child_handler;
+    sv.sa_handler = afp_goaway; /* handler for all sigs */
+
     sigemptyset( &sv.sa_mask );
     sigaddset(&sv.sa_mask, SIGALRM);
     sigaddset(&sv.sa_mask, SIGHUP);
@@ -286,7 +303,6 @@ int main(int ac, char **av)
         exit(EXITERR_SYS);
     }
 
-    sv.sa_handler = afp_goaway;
     sigemptyset( &sv.sa_mask );
     sigaddset(&sv.sa_mask, SIGALRM);
     sigaddset(&sv.sa_mask, SIGTERM);
@@ -374,6 +390,7 @@ int main(int ac, char **av)
     afp_child_t *child;
     int fd[2];  /* we only use one, but server_child_add expects [2] */
     pid_t pid;
+    int saveerrno;
 
     /* wait for an appleshare connection. parent remains in the loop
      * while the children get handled by afp_over_{asp,dsi}.  this is
@@ -386,7 +403,13 @@ int main(int ac, char **av)
         pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
         ret = poll(fdset, fdset_used, -1);
         pthread_sigmask(SIG_BLOCK, &sigs, NULL);
-        int saveerrno = errno;
+        saveerrno = errno;
+
+        if (gotsigchld) {
+            gotsigchld = 0;
+            child_handler();
+            continue;
+        }
 
         if (reloadconfig) {
             nologin++;
@@ -445,7 +468,7 @@ int main(int ac, char **av)
                         fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fds[0]);
                         close(child->ipc_fds[0]);
                         child->ipc_fds[0] = -1;
-                        if (child->disasociated) {
+                        if ((default_options.flags & OPTION_KEEPSESSIONS) && child->disasociated) {
                             LOG(log_note, logtype_afpd, "main: removing reattached child[%u]", child->pid);
                             server_child_remove(server_children, CHILD_DSIFORK, child->pid);
                         }
index cca15f575ace63d295d9b7755584f7cef52845a5..14dab835dcc8195787db677de188b13174de6b2d 100644 (file)
@@ -43,6 +43,7 @@
 #define OPTION_UUID          (1 << 7)
 #define OPTION_ACL2MACCESS   (1 << 8)
 #define OPTION_NOZEROCONF    (1 << 9)
+#define OPTION_KEEPSESSIONS  (1 << 10) /* preserve sessions across master afpd restart with SIGQUIT */
 
 #ifdef FORCE_UIDGID
 /* set up a structure for this */
@@ -127,18 +128,16 @@ typedef struct _AFPObj {
 /* typedef for AFP functions handlers */
 typedef int (*AFPCmd)(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf,  size_t *rbuflen);
 
-/* afp_dsi.c */
-extern AFPObj *AFPobj;
-
-extern int             afp_version;
-extern int             afp_errno;
-extern unsigned char   nologin;
-extern struct dir      *curdir;
-extern char            getwdbuf[];
-
-/* FIXME CNID */
-extern const char *Cnid_srv;
-extern const char *Cnid_port;
+/* Global variables */
+extern AFPObj             *AFPobj;
+extern int                afp_version;
+extern int                afp_errno;
+extern unsigned char      nologin;
+extern struct dir         *curdir;
+extern char               getwdbuf[];
+extern struct afp_options default_options;
+extern const char         *Cnid_srv;
+extern const char         *Cnid_port;
 
 extern int  get_afp_errno   (const int param);
 extern void afp_options_init (struct afp_options *);