]> git.sur5r.net Git - openldap/commitdiff
ITS#4108 Cleanup accept/close race conditions.
authorHoward Chu <hyc@openldap.org>
Sat, 29 Oct 2005 04:17:56 +0000 (04:17 +0000)
committerHoward Chu <hyc@openldap.org>
Sat, 29 Oct 2005 04:17:56 +0000 (04:17 +0000)
servers/slapd/connection.c
servers/slapd/daemon.c
servers/slapd/proto-slap.h

index eb7dd474edb7c3ef9a43f476b42d3483dc2a5857..e8773c0fe274fecd69470964d1c576b97c4e1e45 100644 (file)
@@ -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;
        }
index 0c59f3c89c779031a283a31f5232fdf527171c94..40b0ecee548e5d4ccec954ffbab922089ace88f8 100644 (file)
@@ -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 ) {
index b4cea81cf1121a4c00e913e39afea064f1d6513a..623a36c655bbfccbd9a2637384156171e1f533b7 100644 (file)
@@ -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;