From 19eca33ca311d002bf94f21a084b985b4f5efc45 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Mon, 3 Jun 2002 16:47:43 +0000 Subject: [PATCH] Gentile HUP shutdown from Hallvard --- doc/man/man5/slapd.conf.5 | 16 ++++++++ servers/slapd/config.c | 18 +++++++++ servers/slapd/daemon.c | 80 +++++++++++++++++++++++++++++--------- servers/slapd/proto-slap.h | 1 + 4 files changed, 97 insertions(+), 18 deletions(-) diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5 index 3c9ed2bc52..9a22026da7 100644 --- a/doc/man/man5/slapd.conf.5 +++ b/doc/man/man5/slapd.conf.5 @@ -204,6 +204,22 @@ disables Start TLS from forcing session to anonymous status (see also disables StartTLS if authenticated (see also .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 an idle client connection. A idletimeout of 0 disables this diff --git a/servers/slapd/config.c b/servers/slapd/config.c index e5dcdbe1c7..d89f9cb21b 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -40,6 +41,7 @@ slap_mask_t global_disallows = 0; slap_mask_t global_requires = 0; slap_ssf_set_t global_ssf_set; char *replogfile; +int global_gentlehup = 0; int global_idletimeout = 0; char *global_host = NULL; char *global_realm = NULL; @@ -2038,6 +2040,22 @@ read_config( const char *fname ) } } +#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 */ } else if ( strcasecmp( cargv[0], "idletimeout" ) == 0 ) { int i; diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c index 2ab0fa769f..3dc4cdbcf1 100644 --- a/servers/slapd/daemon.c +++ b/servers/slapd/daemon.c @@ -55,12 +55,12 @@ do { if (w) tcp_write( wake_sds[1], "0", 1 ); } while(0) #ifndef HAVE_WINSOCK 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 /* In winsock, accept() returns values higher than dtblsize @@ -192,6 +192,8 @@ static void slapd_add(ber_socket_t s) { } #endif + slap_daemon.sd_nactives++; + FD_SET( s, &slap_daemon.sd_actives ); FD_SET( s, &slap_daemon.sd_readers ); @@ -216,6 +218,8 @@ static void slapd_add(ber_socket_t s) { void slapd_remove(ber_socket_t s, int wake) { ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); + slap_daemon.sd_nactives--; + #ifdef NEW_LOGGING LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1, "slapd_remove: removing %ld%s%s\n", @@ -233,7 +237,7 @@ void slapd_remove(ber_socket_t s, int wake) { FD_CLR( s, &slap_daemon.sd_writers ); ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); - WAKE_LISTENER(wake); + WAKE_LISTENER(wake || slapd_gentle_shutdown < 0); } void slapd_clr_write(ber_socket_t s, int wake) { @@ -980,6 +984,34 @@ slapd_daemon_destroy(void) } +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( void *ptr @@ -1066,6 +1098,26 @@ slapd_daemon_task( } } +#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 ); @@ -1716,21 +1768,8 @@ slapd_daemon_task( #endif } - 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; @@ -1862,6 +1901,11 @@ slap_sig_shutdown( int sig ) 0, 0, 0); #endif else +#endif +#ifdef SIGHUP + if (sig == SIGHUP && global_gentlehup && slapd_gentle_shutdown == 0) + slapd_gentle_shutdown = 1; + else #endif slapd_shutdown = 1; diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 92bd607b88..f80e53969a 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -1017,6 +1017,7 @@ LDAP_SLAPD_V (const char) Versionstr[]; LDAP_SLAPD_V (struct slap_limits_set) deflimit; 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; LDAP_SLAPD_V (char *) global_host; -- 2.39.5