From a4570992d760645ebc723cda32e4623496b69f93 Mon Sep 17 00:00:00 2001 From: Quanah Gibson-Mount <quanah@openldap.org> Date: Wed, 1 Jul 2009 19:01:58 +0000 Subject: [PATCH] ITS#5836,ITS#6089 --- CHANGES | 2 ++ servers/slapd/result.c | 26 +++++++++++++++++--------- servers/slapd/slap.h | 1 + 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index 961d69eab8..ebb822784d 100644 --- a/CHANGES +++ b/CHANGES @@ -15,8 +15,10 @@ OpenLDAP 2.4.17 Engineering Fixed slapd bind race condition (ITS#6189) Fixed slapd cancel behavior (ITS#6137) Fixed slapd cert validation (ITS#6098) + Fixed slapd connection_destroy assert (ITS#6089) Fixed slapd errno handling (ITS#6037) Fixed slapd global alloc handling (ITS#6054) + Fixed slapd hung writers (ITS#5836) Fixed slapd ldapi issues (ITS#6056) Fixed slapd moduleload with static backends and modules (ITS#6016) Fixed slapd normalization of updated schema attributes (ITS#5540) diff --git a/servers/slapd/result.c b/servers/slapd/result.c index 4b222da640..3ce9e29bd9 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -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 ) diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index a47d1bb54b..a89d7124da 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -2810,6 +2810,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 */ -- GitLab