From: Howard Chu Date: Sun, 13 Sep 2020 06:45:28 +0000 (+0100) Subject: ITS#9338 alternate fix X-Git-Tag: OPENLDAP_REL_ENG_2_5_0ALPHA~10^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9a3e63ba000fd3a068e9955287cd7f4182be02c8;p=thirdparty%2Fopenldap.git ITS#9338 alternate fix Don't resume pending ops unless there are no other threads waiting to write --- diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index e9130a9d0b..843ee03488 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -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; diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index cd509ccfa3..7a3cb5718f 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -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 )); diff --git a/servers/slapd/result.c b/servers/slapd/result.c index c0bafabecf..d571791187 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -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; }