From: Howard Chu Date: Sat, 29 Oct 2005 04:17:56 +0000 (+0000) Subject: ITS#4108 Cleanup accept/close race conditions. X-Git-Tag: OPENLDAP_REL_ENG_2_2_MP~175 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=4bb234bac847d01ee205a3b60c150dcd7f5ee180;p=openldap ITS#4108 Cleanup accept/close race conditions. --- diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index eb7dd474ed..e8773c0fe2 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -844,17 +844,19 @@ connection_destroy( Connection *c ) } ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd ); + slapd_sd_lock(); + ber_sockbuf_free( c->c_sb ); if ( sd != AC_SOCKET_INVALID ) { - slapd_remove( sd, 1, 0 ); + slapd_remove( sd, 1, 0, 1 ); Statslog( LDAP_DEBUG_STATS, (close_reason ? "conn=%lu fd=%ld closed (%s)\n" : "conn=%lu fd=%ld closed\n"), connid, (long) sd, close_reason, 0, 0 ); + } else { + slapd_sd_unlock(); } - ber_sockbuf_free( c->c_sb ); - c->c_sb = ber_sockbuf_alloc( ); { @@ -1389,6 +1391,7 @@ void connection_client_stop( c->c_conn_state = SLAP_C_INVALID; c->c_struct_state = SLAP_C_UNUSED; c->c_close_reason = "?"; /* should never be needed */ + slapd_sd_lock(); ber_sockbuf_free( c->c_sb ); c->c_sb = ber_sockbuf_alloc( ); { @@ -1396,7 +1399,7 @@ void connection_client_stop( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max ); } - slapd_remove( s, 0, 1 ); + slapd_remove( s, 0, 1, 1 ); connection_return( c ); } @@ -1414,15 +1417,13 @@ static void* connection_read_thread( void* ctx, void* argv ) * the first one is returned with new_op */ if( ( rc = connection_read( s, &new_op ) ) < 0 ) { - Debug( LDAP_DEBUG_TRACE, "connection_read(%d) error\n", s, 0, 0 ); - tcp_close( s ); + Debug( LDAP_DEBUG_CONNS, "connection_read(%d) error\n", s, 0, 0 ); return (void*)(long)rc; } /* execute the queued request in the same thread */ if( new_op ) { - rc = (long)connection_operation( - ldap_pvt_thread_pool_context(), new_op ); + rc = (long)connection_operation( ctx, new_op ); } return (void*)(long)rc; @@ -1437,7 +1438,9 @@ int connection_read_activate( ber_socket_t s ) * thread reads data on it. Otherwise the listener thread will repeatedly * submit the same event on it to the pool. */ - slapd_clr_read( s, 0 ); + rc = slapd_clr_read( s, 0 ); + if ( rc ) + return rc; rc = ldap_pvt_thread_pool_submit( &connection_pool, connection_read_thread, (void *)(long)s ); @@ -1473,7 +1476,6 @@ int connection_read(ber_socket_t s) Debug( LDAP_DEBUG_ANY, "connection_read(%ld): no connection!\n", (long) s, 0, 0 ); - slapd_remove(s, 1, 0); ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX(s) ); return -1; @@ -2080,7 +2082,6 @@ int connection_write(ber_socket_t s) Debug( LDAP_DEBUG_ANY, "connection_write(%ld): no connection!\n", (long)s, 0, 0 ); - slapd_remove(s, 1, 0); ldap_pvt_thread_mutex_unlock( MCA_GET_CONN_MUTEX( s ) ); return -1; } diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c index 0c59f3c89c..40b0ecee54 100644 --- a/servers/slapd/daemon.c +++ b/servers/slapd/daemon.c @@ -452,18 +452,32 @@ static void slapd_add(ber_socket_t s, int isactive, Listener *sl) { #endif } +void slapd_sd_lock() +{ + ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); +} + +void slapd_sd_unlock() +{ + ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); +} + /* * Remove the descriptor from daemon control */ void slapd_remove( ber_socket_t s, int wasactive, - int wake ) + int wake, + int locked ) { int waswriter; int wasreader; - ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); + if ( !locked ) + ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); + + assert( SLAP_SOCK_IS_ACTIVE( s )); if ( wasactive ) slap_daemon.sd_nactives--; @@ -533,14 +547,18 @@ void slapd_set_write(ber_socket_t s, int wake) { WAKE_LISTENER(wake); } -void slapd_clr_read(ber_socket_t s, int wake) { +int slapd_clr_read(ber_socket_t s, int wake) { + int rc = 1; ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); - assert( SLAP_SOCK_IS_ACTIVE( s )); - SLAP_SOCK_CLR_READ( s ); - + if ( SLAP_SOCK_IS_ACTIVE( s )) { + SLAP_SOCK_CLR_READ( s ); + rc = 0; + } ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); - WAKE_LISTENER(wake); + if ( !rc ) + WAKE_LISTENER(wake); + return rc; } void slapd_set_read(ber_socket_t s, int wake) { @@ -1212,7 +1230,7 @@ close_listeners( Listener *lr = slap_listeners[l]; if ( lr->sl_sd != AC_SOCKET_INVALID ) { - if ( remove ) slapd_remove( lr->sl_sd, 0, 0 ); + if ( remove ) slapd_remove( lr->sl_sd, 0, 0, 0 ); #ifdef LDAP_PF_LOCAL if ( lr->sl_sa.sa_addr.sa_family == AF_LOCAL ) { diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index b4cea81cf1..623a36c655 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -718,7 +718,10 @@ LDAP_SLAPD_F (int) slapd_daemon_init( const char *urls ); LDAP_SLAPD_F (int) slapd_daemon_destroy(void); LDAP_SLAPD_F (int) slapd_daemon(void); LDAP_SLAPD_F (Listener **) slapd_get_listeners LDAP_P((void)); -LDAP_SLAPD_F (void) slapd_remove LDAP_P((ber_socket_t s, int wasactive, int wake)); +LDAP_SLAPD_F (void) slapd_remove LDAP_P((ber_socket_t s, int wasactive, + int wake, int locked )); +LDAP_SLAPD_F (void) slapd_sd_lock(); +LDAP_SLAPD_F (void) slapd_sd_unlock(); LDAP_SLAPD_F (RETSIGTYPE) slap_sig_shutdown LDAP_P((int sig)); LDAP_SLAPD_F (RETSIGTYPE) slap_sig_wake LDAP_P((int sig)); @@ -727,7 +730,7 @@ LDAP_SLAPD_F (void) slap_wake_listener LDAP_P((void)); LDAP_SLAPD_F (void) slapd_set_write LDAP_P((ber_socket_t s, int wake)); LDAP_SLAPD_F (void) slapd_clr_write LDAP_P((ber_socket_t s, int wake)); LDAP_SLAPD_F (void) slapd_set_read LDAP_P((ber_socket_t s, int wake)); -LDAP_SLAPD_F (void) slapd_clr_read LDAP_P((ber_socket_t s, int wake)); +LDAP_SLAPD_F (int) slapd_clr_read LDAP_P((ber_socket_t s, int wake)); LDAP_SLAPD_V (volatile sig_atomic_t) slapd_abrupt_shutdown; LDAP_SLAPD_V (volatile sig_atomic_t) slapd_shutdown;