]> git.sur5r.net Git - openldap/commitdiff
ITS#5835, ITS#5886
authorQuanah Gibson-Mount <quanah@openldap.org>
Wed, 21 Jan 2009 06:06:07 +0000 (06:06 +0000)
committerQuanah Gibson-Mount <quanah@openldap.org>
Wed, 21 Jan 2009 06:06:07 +0000 (06:06 +0000)
CHANGES
servers/slapd/connection.c
servers/slapd/daemon.c
servers/slapd/proto-slap.h
servers/slapd/result.c
servers/slapd/slap.h
servers/slapd/slapi/slapi_ops.c

diff --git a/CHANGES b/CHANGES
index 2bb9ca2e25d358b0394a601ac05ed74fff1229d1..22caa824763e3ff9ede86a51aa8f6faa74bb9ae7 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -11,6 +11,8 @@ OpenLDAP 2.4.14 Engineering
        Added slapo-rwm newRDN rewriting (ITS#5834)
        Fixed slapd bconfig to return error codes (ITS#5867)
        Fixed slapd bconfig encoding incorrectly (ITS#5897)
+       Fixed slapd connection assert (ITS#5835)
+       Fixed slapd epoll handling (ITS#5886)
        Fixed slapd syncrepl rename handling (ITS#5809)
        Fixed slapd syncrepl MMR when adding new server (ITS#5850)
        Fixed slapd syncrepl replication with glued DB (ITS#5866)
index 4c3178e338c74a58b00cc00beabccb38e8f3259d..7c40df58584347e6ccef8207743785f25db82a35 100644 (file)
@@ -163,8 +163,10 @@ int connections_destroy(void)
                if( connections[i].c_struct_state != SLAP_C_UNINITIALIZED ) {
                        ber_sockbuf_free( connections[i].c_sb );
                        ldap_pvt_thread_mutex_destroy( &connections[i].c_mutex );
-                       ldap_pvt_thread_mutex_destroy( &connections[i].c_write_mutex );
-                       ldap_pvt_thread_cond_destroy( &connections[i].c_write_cv );
+                       ldap_pvt_thread_mutex_destroy( &connections[i].c_write1_mutex );
+                       ldap_pvt_thread_mutex_destroy( &connections[i].c_write2_mutex );
+                       ldap_pvt_thread_cond_destroy( &connections[i].c_write1_cv );
+                       ldap_pvt_thread_cond_destroy( &connections[i].c_write2_cv );
 #ifdef LDAP_SLAPI
                        if ( slapi_plugins_used ) {
                                slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION,
@@ -384,8 +386,10 @@ Connection * connection_init(
 
                /* should check status of thread calls */
                ldap_pvt_thread_mutex_init( &c->c_mutex );
-               ldap_pvt_thread_mutex_init( &c->c_write_mutex );
-               ldap_pvt_thread_cond_init( &c->c_write_cv );
+               ldap_pvt_thread_mutex_init( &c->c_write1_mutex );
+               ldap_pvt_thread_mutex_init( &c->c_write2_mutex );
+               ldap_pvt_thread_cond_init( &c->c_write1_cv );
+               ldap_pvt_thread_cond_init( &c->c_write2_cv );
 
 #ifdef LDAP_SLAPI
                if ( slapi_plugins_used ) {
@@ -417,6 +421,7 @@ Connection * connection_init(
        assert( c->c_sasl_bindop == NULL );
        assert( c->c_currentber == NULL );
        assert( c->c_writewaiter == 0);
+       assert( c->c_writers == 0);
 
        c->c_listener = listener;
        c->c_sd = s;
@@ -593,6 +598,7 @@ connection_destroy( Connection *c )
        assert( LDAP_STAILQ_EMPTY(&c->c_txn_ops) );
 #endif
        assert( c->c_writewaiter == 0);
+       assert( c->c_writers == 0);
 
        /* only for stats (print -1 as "%lu" may give unexpected results ;) */
        connid = c->c_connid;
@@ -752,18 +758,24 @@ void connection_closing( Connection *c, const char *why )
                connection_abandon( c );
 
                /* wake write blocked operations */
-               if ( c->c_writewaiter ) {
-                       ldap_pvt_thread_cond_signal( &c->c_write_cv );
-                       /* ITS#4667 this may allow another thread to drop into
-                        * connection_resched / connection_close before we
-                        * finish, but that's OK.
-                        */
-                       slapd_clr_write( c->c_sd, 1 );
-                       ldap_pvt_thread_mutex_unlock( &c->c_mutex );
-                       ldap_pvt_thread_mutex_lock( &c->c_write_mutex );
-                       ldap_pvt_thread_mutex_lock( &c->c_mutex );
-                       ldap_pvt_thread_mutex_unlock( &c->c_write_mutex );
+               ldap_pvt_thread_mutex_lock( &c->c_write1_mutex );
+               if ( c->c_writers > 0 ) {
+                       c->c_writers = -c->c_writers;
+                       ldap_pvt_thread_cond_broadcast( &c->c_write1_cv );
+                       ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
+                       if ( c->c_writewaiter ) {
+                               ldap_pvt_thread_mutex_lock( &c->c_write2_mutex );
+                               ldap_pvt_thread_cond_signal( &c->c_write2_cv );
+                               slapd_clr_write( c->c_sd, 1 );
+                               ldap_pvt_thread_mutex_unlock( &c->c_write2_mutex );
+                       }
+                       ldap_pvt_thread_mutex_lock( &c->c_write1_mutex );
+                       while ( c->c_writers ) {
+                               ldap_pvt_thread_cond_wait( &c->c_write1_cv, &c->c_write1_mutex );
+                       }
+                       ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
                } else {
+                       ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
                        slapd_clr_write( c->c_sd, 1 );
                }
 
@@ -778,11 +790,6 @@ connection_close( Connection *c )
 {
        assert( connections != NULL );
        assert( c != NULL );
-
-       /* ITS#4667 we may have gotten here twice */
-       if ( c->c_conn_state == SLAP_C_INVALID )
-               return;
-
        assert( c->c_struct_state == SLAP_C_USED );
        assert( c->c_conn_state == SLAP_C_CLOSING );
 
@@ -1174,7 +1181,7 @@ void connection_client_stop(
 
        /* get (locked) connection */
        c = connection_get( s );
-       
+
        assert( c->c_conn_state == SLAP_C_CLIENT );
 
        c->c_listener = NULL;
@@ -1246,6 +1253,24 @@ int connection_read_activate( ber_socket_t s )
        return rc;
 }
 
+void
+connection_hangup( ber_socket_t s )
+{
+       Connection *c;
+
+       c = connection_get( s );
+       if ( c ) {
+               if ( c->c_conn_state == SLAP_C_CLIENT ) {
+                       connection_return( c );
+                       connection_read_activate( s );
+               } else {
+                       connection_closing( c, "connection lost" );
+                       connection_close( c );
+                       connection_return( c );
+               }
+       }
+}
+
 static int
 connection_read( ber_socket_t s, conn_readinfo *cri )
 {
@@ -1831,7 +1856,7 @@ int connection_write(ber_socket_t s)
        Debug( LDAP_DEBUG_TRACE,
                "connection_write(%d): waking output for id=%lu\n",
                s, c->c_connid, 0 );
-       ldap_pvt_thread_cond_signal( &c->c_write_cv );
+       ldap_pvt_thread_cond_signal( &c->c_write2_cv );
 
        if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) ) {
                slapd_set_read( s, 1 );
index fea9d35e2324ee5f9c57fda37ecb9922e10d709a..7f953e4d329abe40b4d3f6ed0e04da5a9d590839 100644 (file)
@@ -2495,7 +2495,7 @@ slapd_daemon_task(
 #endif /* LDAP_DEBUG */
 
                for ( i = 0; i < ns; i++ ) {
-                       int rc = 1, fd;
+                       int rc = 1, fd, w = 0;
 
                        if ( SLAP_EVENT_IS_LISTENER( i ) ) {
                                rc = slap_listener_activate( SLAP_EVENT_LISTENER( i ) );
@@ -2522,6 +2522,7 @@ slapd_daemon_task(
                                                fd, 0, 0 );
 
                                        SLAP_EVENT_CLR_WRITE( i );
+                                       w = 1;
 
                                        /*
                                         * NOTE: it is possible that the connection was closed
@@ -2541,9 +2542,10 @@ slapd_daemon_task(
 
                                        SLAP_EVENT_CLR_READ( i );
                                        connection_read_activate( fd );
-                               } else {
+                               } else if ( !w ) {
                                        Debug( LDAP_DEBUG_CONNS,
                                                "daemon: hangup on %d\n", fd, 0, 0 );
+                                       connection_hangup( fd );
                                }
                        }
                }
index 5d07c4c259e5ef59a158b501552d38ba7128fab7..4b17b54a59f942ac9a4ee271118178339f09a4a9 100644 (file)
@@ -745,6 +745,7 @@ LDAP_SLAPD_F (Connection *) connection_init LDAP_P((
 
 LDAP_SLAPD_F (void) connection_closing LDAP_P((
        Connection *c, const char *why ));
+LDAP_SLAPD_F (void) connection_hangup LDAP_P(( ber_socket_t fd ));
 LDAP_SLAPD_F (int) connection_state_closing LDAP_P(( Connection *c ));
 LDAP_SLAPD_F (const char *) connection_state2str LDAP_P(( int state ))
        LDAP_GCCATTR((const));
index a2e7343eb6ceca4568d990848114e4a317525405..c9351fb47776d023eb0c7d1c2dc8bfe2e0dc9b58 100644 (file)
@@ -137,27 +137,44 @@ static long send_ldap_ber(
        BerElement *ber )
 {
        ber_len_t bytes;
+       long ret = 0;
+       int closing = 0;
 
        ber_get_option( ber, LBER_OPT_BER_BYTES_TO_WRITE, &bytes );
 
        /* write only one pdu at a time - wait til it's our turn */
-       ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
+       ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
+       if ( connection_state_closing( conn )) {
+               ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
+               return 0;
+       }
+       while ( conn->c_writers > 0 ) {
+               ldap_pvt_thread_cond_wait( &conn->c_write1_cv, &conn->c_write1_mutex );
+       }
+       /* connection was closed under us */
+       if ( conn->c_writers < 0 ) {
+               closing = 1;
+               /* we're the last waiter, let the closer continue */
+               if ( conn->c_writers == -1 )
+                       ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
+       }
 
-       /* lock the connection */ 
-       ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+       conn->c_writers++;
+       ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
+
+       if ( closing )
+               return 0;
 
        /* write the pdu */
        while( 1 ) {
                int err;
 
-               if ( connection_state_closing( conn ) ) {
-                       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
-                       ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
-
-                       return 0;
-               }
+               /* lock the connection */ 
+               ldap_pvt_thread_mutex_lock( &conn->c_mutex );
 
                if ( ber_flush2( conn->c_sb, ber, LBER_FLUSH_FREE_NEVER ) == 0 ) {
+                       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+                       ret = bytes;
                        break;
                }
 
@@ -176,23 +193,41 @@ static long send_ldap_ber(
                        connection_closing( conn, "connection lost on write" );
 
                        ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
-                       ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
 
-                       return( -1 );
+                       ret = -1;
+                       break;
                }
 
                /* wait for socket to be write-ready */
+               ldap_pvt_thread_mutex_lock( &conn->c_write2_mutex );
                conn->c_writewaiter = 1;
                slapd_set_write( conn->c_sd, 1 );
 
-               ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
+               ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+               ldap_pvt_thread_cond_wait( &conn->c_write2_cv, &conn->c_write2_mutex );
                conn->c_writewaiter = 0;
+               ldap_pvt_thread_mutex_unlock( &conn->c_write2_mutex );
+               ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
+               closing = ( conn->c_writers < 0 );
+               ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
+               if ( closing ) {
+                       ret = 0;
+                       break;
+               }
        }
 
-       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
-       ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
+       ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
+       if ( conn->c_writers < 0 ) {
+               conn->c_writers++;
+               if ( !conn->c_writers )
+                       ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
+       } else {
+               conn->c_writers--;
+               ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
+       }
+       ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
 
-       return bytes;
+       return ret;
 }
 
 static int
index dadd88d5c92db7cc444587eeb1c056e5d29f7468..b4e50e39123094c08e7a4f01222d2da3f55aa77c 100644 (file)
@@ -2801,14 +2801,17 @@ struct Connection {
        LDAP_STAILQ_HEAD(c_o, Operation) c_ops; /* list of operations being processed */
        LDAP_STAILQ_HEAD(c_po, Operation) c_pending_ops;        /* list of pending operations */
 
-       ldap_pvt_thread_mutex_t c_write_mutex;  /* only one pdu written at a time */
-       ldap_pvt_thread_cond_t  c_write_cv;             /* used to wait for sd write-ready*/
+       ldap_pvt_thread_mutex_t c_write1_mutex; /* only one pdu written at a time */
+       ldap_pvt_thread_cond_t  c_write1_cv;    /* only one pdu written at a time */
+       ldap_pvt_thread_mutex_t c_write2_mutex; /* used to wait for sd write-ready */
+       ldap_pvt_thread_cond_t  c_write2_cv;    /* used to wait for sd write-ready*/
 
        BerElement      *c_currentber;  /* ber we're attempting to read */
+       int                     c_writers;              /* number of writers waiting */
 
        char            c_sasl_bind_in_progress;        /* multi-op bind in progress */
+       char            c_writewaiter;  /* true if blocked on write */
 
-       char            c_writewaiter;  /* true if writer is waiting */
 
 #define        CONN_IS_TLS     1
 #define        CONN_IS_UDP     2
index e7aab5d8d370532d92b2ed06f8a443c49777ef85..eaf4060b01739d929894a98c9ac0191b9a3bf269 100644 (file)
@@ -224,8 +224,10 @@ slapi_int_connection_init_pb( Slapi_PBlock *pb, ber_tag_t tag )
 
        /* should check status of thread calls */
        ldap_pvt_thread_mutex_init( &conn->c_mutex );
-       ldap_pvt_thread_mutex_init( &conn->c_write_mutex );
-       ldap_pvt_thread_cond_init( &conn->c_write_cv );
+       ldap_pvt_thread_mutex_init( &conn->c_write1_mutex );
+       ldap_pvt_thread_mutex_init( &conn->c_write2_mutex );
+       ldap_pvt_thread_cond_init( &conn->c_write1_cv );
+       ldap_pvt_thread_cond_init( &conn->c_write2_cv );
 
        ldap_pvt_thread_mutex_lock( &conn->c_mutex );