From b78d1b52c8731732206b5f61a8a48de71dfa3d61 Mon Sep 17 00:00:00 2001 From: Frank Lahm Date: Sat, 24 Mar 2012 14:15:03 +0100 Subject: [PATCH] Fix keep session stuff --- etc/cnid_dbd/cnid_metad.c | 16 +++++++++++----- etc/netatalk/netatalk.c | 20 +++++++++----------- man/man5/afp.conf.5.tmpl | 6 ++++-- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/etc/cnid_dbd/cnid_metad.c b/etc/cnid_dbd/cnid_metad.c index dcc70123..d6fbcb06 100644 --- a/etc/cnid_dbd/cnid_metad.c +++ b/etc/cnid_dbd/cnid_metad.c @@ -128,11 +128,13 @@ static void daemon_exit(int i) } /* ------------------ */ -static void sigterm_handler(int sig) +static void sig_handler(int sig) { switch( sig ) { - case SIGTERM : - LOG(log_info, logtype_afpd, "shutting down on signal %d", sig ); + case SIGTERM: + case SIGQUIT: + LOG(log_note, logtype_afpd, "shutting down on %s", + sig == SIGTERM ? "SIGTERM" : "SIGQUIT"); break; default : LOG(log_error, logtype_afpd, "unexpected signal: %d", sig); @@ -380,13 +382,17 @@ static void set_signal(void) daemon_exit(EXITERR_SYS); } - /* Catch SIGTERM */ - sv.sa_handler = sigterm_handler; + /* Catch SIGTERM and SIGQUIT */ + sv.sa_handler = sig_handler; sigfillset(&sv.sa_mask ); if (sigaction(SIGTERM, &sv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "sigaction: %s", strerror(errno) ); daemon_exit(EXITERR_SYS); } + if (sigaction(SIGQUIT, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "sigaction: %s", strerror(errno) ); + daemon_exit(EXITERR_SYS); + } /* Ignore the rest */ sv.sa_handler = SIG_IGN; diff --git a/etc/netatalk/netatalk.c b/etc/netatalk/netatalk.c index ec323e21..7c7f1003 100644 --- a/etc/netatalk/netatalk.c +++ b/etc/netatalk/netatalk.c @@ -40,7 +40,7 @@ /* forward declaration */ static pid_t run_process(const char *path, ...); -static void kill_childs(int count, int sig, ...); +static void kill_childs(int sig, ...); /* static variables */ static AFPObj obj; @@ -93,8 +93,7 @@ static void sigterm_cb(evutil_socket_t fd, short what, void *arg) static void sigquit_cb(evutil_socket_t fd, short what, void *arg) { LOG(log_note, logtype_afpd, "Exiting on SIGQUIT"); - in_shutdown = 1; - event_base_loopbreak(base); + kill_childs(SIGQUIT, &afpd_pid, &cnid_metad_pid, NULL); } /* SIGCHLD callback */ @@ -153,16 +152,15 @@ static void sigchld_cb(evutil_socket_t fd, short what, void *arg) * helper functions ******************************************************************/ -/* kill "count" processes passed as varargs of type "pid_t *" */ -static void kill_childs(int count, int sig, ...) +/* kill processes passed as varargs of type "pid_t *", terminate list with NULL */ +static void kill_childs(int sig, ...) { va_list args; pid_t *pid; va_start(args, sig); - while (count--) { - pid = va_arg(args, pid_t *); + while ((pid = va_arg(args, pid_t *)) != NULL) { if (*pid == -1) continue; kill(*pid, sig); @@ -272,7 +270,7 @@ int main(int argc, char **argv) } sigterm_ev = event_new(base, SIGTERM, EV_SIGNAL, sigterm_cb, NULL); - sigquit_ev = event_new(base, SIGQUIT, EV_SIGNAL, sigquit_cb, NULL); + sigquit_ev = event_new(base, SIGQUIT, EV_SIGNAL | EV_PERSIST, sigquit_cb, NULL); sigchld_ev = event_new(base, SIGCHLD, EV_SIGNAL | EV_PERSIST, sigchld_cb, NULL); event_add(sigterm_ev, NULL); @@ -288,7 +286,7 @@ int main(int argc, char **argv) /* run the event loop */ ret = event_base_dispatch(base); - /* got SIGTERM or similar, so we're going to shutdown */ + /* got SIGTERM so we're going to shutdown */ /* block any signal but SIGCHLD */ sigfillset(&blocksigs); @@ -304,7 +302,7 @@ int main(int argc, char **argv) event_del(sigquit_ev); /* run the event loop again, waiting for child to exit on SIGTERM for KILL_GRACETIME seconds */ - kill_childs(2, SIGTERM, &afpd_pid, &cnid_metad_pid); + kill_childs(SIGTERM, &afpd_pid, &cnid_metad_pid, NULL); ret = event_base_dispatch(base); if (afpd_pid != -1 || cnid_metad_pid != -1) { @@ -312,7 +310,7 @@ int main(int argc, char **argv) LOG(log_error, logtype_afpd, "AFP service did not shutdown, killing it"); if (cnid_metad_pid != -1) LOG(log_error, logtype_afpd, "CNID database service did not shutdown, killing it"); - kill_childs(2, SIGKILL, &afpd_pid, &cnid_metad_pid); + kill_childs(SIGKILL, &afpd_pid, &cnid_metad_pid, NULL); } netatalk_exit(ret); } diff --git a/man/man5/afp.conf.5.tmpl b/man/man5/afp.conf.5.tmpl index af6bb4ea..6f2a7515 100644 --- a/man/man5/afp.conf.5.tmpl +++ b/man/man5/afp.conf.5.tmpl @@ -372,7 +372,7 @@ Search scope for user search: .sp .RE .PP -ldap uuuid attr = \fIdn\fR \fB(G)\fR +ldap uuid attr = \fIdn\fR \fB(G)\fR .RS 4 Name of the LDAP attribute with the UUIDs\&. .sp @@ -665,7 +665,9 @@ Use the platform\-specific icon\&. Mac OS X doesn\'t display it\&. .PP keep sessions = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)\fR .RS 4 -Enable "Continuous AFP Service"\&. This means the ability to stop the master afpd process with a SIGQUIT signal, possibly install an afpd update and start the afpd process\&. Existing AFP sessions afpd processes will remain unaffected\&. Technically they will be notified of the master afpd shutdown, sleep 15\-20 seconds and then try to reconnect their IPC channel to the master afpd process\&. If this reconnect fails, the sessions are in an undefined state\&. Therefor it\'s absolutely critical to restart the master process in time! +Enable "Continuous AFP Service"\&. This means restarting AFP and CNID service daemons master processes, but keeping the AFP session processes\&. This can be used to install (most) updates to Netatalk without interruping active AFP sessions\&. Existing AFP sessions will still run the version from before updating, but new AFP sessions will run the updated code\&. After enabling this option when sending SIGQUIT to the +\fInetatalk\fR +service controller process, the AFP and CNID daemons will exit and then the service controller will restart them\&. AFP session processes are notified of the master afpd shutdown, they will then sleep 15\-20 seconds and then try to reconnect their IPC channel to the master afpd process\&. The IPC channel between the AFP master service daemon and the AFP session child is used for keeping session state of AFP sessions in the AFP master process\&. The session state is needed when AFP clients experience eg network outages and try to reconnect to the AFP server\&. .RE .PP map acls = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(G)\fR -- 2.39.2