Patch: Implement 'gentle SIGHUP handling' (ITS#1679) ================ Written by Hallvard B. Furuseth and placed into the public domain. This software is not subject to any license of the University of Oslo. ================ Description from slapd.conf: gentlehup { on | off } A SIGHUP signal will only cause a 'gentle' shutdown-attempt: Slapd will stop listening for new connections, but will not close the connections to the current clients. It terminates when all clients have closed their connections (if they ever do), or - as before - if it receives a SIGTERM signal. This can be useful if you wish to terminate the server and start a new slapd server *with another database*, without disrupting the currently active clients. The default is off. You may wish to use idletimeout along with this option. Implementation note: slap_daemon.sd_nactives, which was unused, is now used to count the number of connections and listeners to the slapd daemon. Hallvard B. Furuseth , March 2002. diff -u2 -r doc/man/man5/slapd.conf.5~ doc/man/man5/slapd.conf.5 --- doc/man/man5/slapd.conf.5~ Thu Feb 7 18:17:24 2002 +++ doc/man/man5/slapd.conf.5 Sun Mar 24 02:36:01 2002 @@ -148,4 +148,20 @@ .BR tls_2_anon ). .TP +.B gentlehup { on | off } +A SIGHUP signal will only cause a 'gentle' shutdown-attempt: +.B Slapd +will stop listening for new connections, but will not close the +connections to the current clients. It terminates when all clients +have closed their connections (if they ever do), or \- as before \- +if it receives a SIGTERM signal. This can be useful if you wish to +terminate the server and start a new +.B slapd +server +.B with another database, +without disrupting the currently active clients. +The default is off. You may wish to use +.B idletimeout +along with this option. +.TP .B idletimeout Specify the number of seconds to wait before forcibly closing diff -u2 -r servers/slapd/config.c~ servers/slapd/config.c --- servers/slapd/config.c~ Sat Feb 9 05:14:17 2002 +++ servers/slapd/config.c Sun Mar 24 02:37:48 2002 @@ -12,4 +12,5 @@ #include #include +#include #include #include @@ -41,4 +42,5 @@ slap_ssf_set_t global_ssf_set; char *replogfile; +int global_gentlehup = 0; int global_idletimeout = 0; char *global_host = NULL; @@ -2019,4 +2021,20 @@ } } + +#ifdef SIGHUP + /* turn on/off gentle SIGHUP handling */ + } else if ( strcasecmp( cargv[0], "gentlehup" ) == 0 ) { + if ( cargc < 2 ) { + Debug( LDAP_DEBUG_ANY, + "%s: line %d: missing on|off in \"gentlehup \" line\n", + fname, lineno, 0 ); + return( 1 ); + } + if ( strcasecmp( cargv[1], "off" ) == 0 ) { + global_gentlehup = 0; + } else { + global_gentlehup = 1; + } +#endif /* set idle timeout value */ diff -u2 -r servers/slapd/daemon.c~ servers/slapd/daemon.c --- servers/slapd/daemon.c~ Mon Jan 28 20:26:55 2002 +++ servers/slapd/daemon.c Sun Mar 24 02:39:22 2002 @@ -57,10 +57,10 @@ static #endif -volatile sig_atomic_t slapd_shutdown = 0; +volatile sig_atomic_t slapd_shutdown = 0, slapd_gentle_shutdown = 0; static struct slap_daemon { ldap_pvt_thread_mutex_t sd_mutex; - int sd_nactives; + ber_socket_t sd_nactives; #ifndef HAVE_WINSOCK @@ -194,4 +194,6 @@ #endif + slap_daemon.sd_nactives++; + FD_SET( s, &slap_daemon.sd_actives ); FD_SET( s, &slap_daemon.sd_readers ); @@ -218,4 +220,6 @@ ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); + slap_daemon.sd_nactives--; + #ifdef NEW_LOGGING LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1, @@ -235,5 +239,5 @@ ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); - WAKE_LISTENER(wake); + WAKE_LISTENER(wake || slapd_gentle_shutdown < 0); } @@ -1090,4 +1094,32 @@ +static void +close_listeners( + int remove +) +{ + int l; + + for ( l = 0; slap_listeners[l] != NULL; l++ ) { + if ( remove ) + slapd_remove( slap_listeners[l]->sl_sd, 0 ); + if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) { +#ifdef LDAP_PF_LOCAL + if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_LOCAL ) { + unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path ); + } +#endif /* LDAP_PF_LOCAL */ + slapd_close( slap_listeners[l]->sl_sd ); + } + if ( slap_listeners[l]->sl_url ) + free ( slap_listeners[l]->sl_url ); + if ( slap_listeners[l]->sl_name ) + free ( slap_listeners[l]->sl_name ); + free ( slap_listeners[l] ); + slap_listeners[l] = NULL; + } +} + + static void * slapd_daemon_task( @@ -1176,4 +1208,24 @@ } +#ifdef SIGHUP + if( slapd_gentle_shutdown ) { + ber_socket_t active; + + if( slapd_gentle_shutdown > 0 ) { + Debug( LDAP_DEBUG_ANY, "slapd gentle shutdown\n", 0, 0, 0 ); + close_listeners( 1 ); + slapd_gentle_shutdown = -1; + } + + ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); + active = slap_daemon.sd_nactives; + ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); + if( active == 0 ) { + slapd_shutdown = -1; + break; + } + } +#endif + FD_ZERO( &writefds ); FD_ZERO( &readfds ); @@ -1829,19 +1881,6 @@ } - for ( l = 0; slap_listeners[l] != NULL; l++ ) { - if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) { -#ifdef LDAP_PF_LOCAL - if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_LOCAL ) { - unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path ); - } -#endif /* LDAP_PF_LOCAL */ - slapd_close( slap_listeners[l]->sl_sd ); - } - if ( slap_listeners[l]->sl_url ) - free ( slap_listeners[l]->sl_url ); - if ( slap_listeners[l]->sl_name ) - free ( slap_listeners[l]->sl_name ); - free ( slap_listeners[l] ); - } + if( slapd_gentle_shutdown >= 0 ) + close_listeners ( 0 ); free ( slap_listeners ); slap_listeners = NULL; @@ -1974,4 +2013,9 @@ 0, 0, 0); #endif + else +#endif +#ifdef SIGHUP + if (sig == SIGHUP && global_gentlehup && slapd_gentle_shutdown == 0) + slapd_gentle_shutdown = 1; else #endif diff -u2 -r servers/slapd/proto-slap.h~ servers/slapd/proto-slap.h --- servers/slapd/proto-slap.h~ Fri Feb 15 16:27:31 2002 +++ servers/slapd/proto-slap.h Sun Mar 24 02:36:01 2002 @@ -987,4 +987,5 @@ LDAP_SLAPD_V (slap_access_t) global_default_access; +LDAP_SLAPD_V (int) global_gentlehup; LDAP_SLAPD_V (int) global_idletimeout; LDAP_SLAPD_V (int) global_schemacheck;