]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#9338 alternate fix
authorHoward Chu <hyc@openldap.org>
Sun, 13 Sep 2020 06:45:28 +0000 (07:45 +0100)
committerQuanah Gibson-Mount <quanah@openldap.org>
Sun, 13 Sep 2020 08:05:31 +0000 (08:05 +0000)
Don't resume pending ops unless there are no other threads
waiting to write

servers/slapd/connection.c
servers/slapd/proto-slap.h
servers/slapd/result.c

index e9130a9d0bf2a4bf430122449cffd88da1b8b337..843ee0348809c70facbfb1d5cc778c79be99f66e 100644 (file)
@@ -2039,6 +2039,34 @@ int connection_write(ber_socket_t s)
        return 0;
 }
 
+int connection_write_resume( Connection *c )
+{
+       Operation *op;
+
+       ldap_pvt_thread_mutex_lock( &c->c_mutex );
+       /* If there are ops pending because of a writewaiter,
+        * start one up.
+        */
+       while ((op = LDAP_STAILQ_FIRST( &c->c_pending_ops )) != NULL) {
+               if ( c->c_n_ops_executing > connection_pool_max/2 ) break;
+
+               LDAP_STAILQ_REMOVE_HEAD( &c->c_pending_ops, o_next );
+               LDAP_STAILQ_NEXT(op, o_next) = NULL;
+
+               /* pending operations should not be marked for abandonment */
+               assert(!op->o_abandon);
+
+               c->c_n_ops_pending--;
+               c->c_n_ops_executing++;
+
+               connection_op_activate( op );
+
+               break;
+       }
+
+       connection_return( c );
+}
+
 #ifdef LDAP_SLAPI
 typedef struct conn_fake_extblock {
        void *eb_conn;
index cd509ccfa320ce913783a4f9e7e3f7b5dac31ad0..7a3cb5718f29c03bb902677484cd065fe9f26b54 100644 (file)
@@ -809,6 +809,7 @@ LDAP_SLAPD_F (const char *) connection_state2str LDAP_P(( int state ))
 
 LDAP_SLAPD_F (int) connection_read_activate LDAP_P((ber_socket_t s));
 LDAP_SLAPD_F (int) connection_write LDAP_P((ber_socket_t s));
+LDAP_SLAPD_F (int) connection_write_resume LDAP_P((Connection *c));
 
 LDAP_SLAPD_F (void) connection_op_finish LDAP_P((
        Operation *op ));
index c0bafabecf888c0ca1589a78f41ccf3be5544adc..d57179118782c3ca8e4a7f9bb928545871cbcc81 100644 (file)
@@ -339,6 +339,7 @@ static long send_ldap_ber(
        ber_len_t bytes;
        long ret = 0;
        char *close_reason;
+       int do_resume = 0;
 
        ber_get_option( ber, LBER_OPT_BER_BYTES_TO_WRITE, &bytes );
 
@@ -404,11 +405,13 @@ fail:
                }
 
                /* wait for socket to be write-ready */
+               do_resume = 1;
                conn->c_writewaiter = 1;
                ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
                ldap_pvt_thread_pool_idle( &connection_pool );
                slap_writewait_play( op );
                err = slapd_wait_writer( conn->c_sd );
+               conn->c_writewaiter = 0;
                ldap_pvt_thread_pool_unidle( &connection_pool );
                ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
                /* 0 is timeout, so we close it.
@@ -419,14 +422,9 @@ fail:
                                close_reason = "writetimeout";
                        else
                                close_reason = "connection lost on writewait";
-                       conn->c_writewaiter = 0;
                        goto fail;
                }
 
-               /* Resched connection if there are pending ops */
-               connection_write( conn->c_sd );
-               conn->c_writewaiter = 0;
-
                if ( conn->c_writers < 0 ) {
                        ret = 0;
                        break;
@@ -435,15 +433,24 @@ fail:
 
        conn->c_writing = 0;
        if ( conn->c_writers < 0 ) {
+               /* shutting down, don't resume any ops */
+               do_resume = 0;
                conn->c_writers++;
                if ( !conn->c_writers )
                        ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
        } else {
                conn->c_writers--;
+               /* other writers are waiting, don't resume any ops */
+               if ( conn->c_writers )
+                       do_resume = 0;
                ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
        }
        ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
 
+       /* If there are no more writers, release a pending op */
+       if ( do_resume )
+               connection_write_resume( conn );
+
        return ret;
 }