]> git.sur5r.net Git - openldap/commitdiff
ITS#5836, #6089 fix c_writers counting
authorHoward Chu <hyc@openldap.org>
Wed, 1 Jul 2009 03:01:08 +0000 (03:01 +0000)
committerHoward Chu <hyc@openldap.org>
Wed, 1 Jul 2009 03:01:08 +0000 (03:01 +0000)
servers/slapd/result.c
servers/slapd/slap.h

index 4b222da6404cd16488ac425c06f736f913ddc1d9..3ce9e29bd9820b2b3f5fc1c6c68b7a9bc3dd0361 100644 (file)
@@ -139,40 +139,46 @@ static long send_ldap_ber(
        Connection *conn = op->o_conn;
        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_write1_mutex );
-       if (( op->o_abandon && !op->o_cancel ) || !connection_valid( conn )) {
+       if (( op->o_abandon && !op->o_cancel ) || !connection_valid( conn ) ||
+               conn->c_writers < 0 ) {
                ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
                return 0;
        }
-       while ( conn->c_writers > 0 ) {
+
+       conn->c_writers++;
+
+       while ( conn->c_writers > 0 && conn->c_writing ) {
                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 );
-       }
-
-       conn->c_writers++;
-
-       if ( closing ) {
+               conn->c_writers++;
                ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
                return 0;
        }
 
+       /* Our turn */
+       conn->c_writing = 1;
+
        /* write the pdu */
        while( 1 ) {
                int err;
 
                /* lock the connection */ 
                if ( ldap_pvt_thread_mutex_trylock( &conn->c_mutex )) {
+                       if ( !connection_valid(conn)) {
+                               ret = 0;
+                               break;
+                       }
                        ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
                        ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
                        if ( conn->c_writers < 0 ) {
@@ -201,6 +207,7 @@ static long send_ldap_ber(
 
                if ( err != EWOULDBLOCK && err != EAGAIN ) {
                        conn->c_writers--;
+                       conn->c_writing = 0;
                        ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
                        connection_closing( conn, "connection lost on write" );
 
@@ -225,6 +232,7 @@ static long send_ldap_ber(
                }
        }
 
+       conn->c_writing = 0;
        if ( conn->c_writers < 0 ) {
                conn->c_writers++;
                if ( !conn->c_writers )
index fa87f6660898dc0ca1f67ad495a444f54e0d6aa3..f5002c60394985ecf43474f57278b6c9c7550eb2 100644 (file)
@@ -2809,6 +2809,7 @@ struct Connection {
 
        BerElement      *c_currentber;  /* ber we're attempting to read */
        int                     c_writers;              /* number of writers waiting */
+       char            c_writing;              /* someone is writing */
 
        char            c_sasl_bind_in_progress;        /* multi-op bind in progress */
        char            c_writewaiter;  /* true if blocked on write */