From 868cb32225ece4e5ff8987a56c64d2765508a2b4 Mon Sep 17 00:00:00 2001
From: Quanah Gibson-Mount <quanah@openldap.org>
Date: Sat, 29 Aug 2009 00:39:44 +0000
Subject: [PATCH] ITS#6276

---
 CHANGES                    |  1 +
 servers/slapd/connection.c | 52 +++++++++++++++++++++++---------------
 2 files changed, 33 insertions(+), 20 deletions(-)

diff --git a/CHANGES b/CHANGES
index 840b7bedd1..c237f3c1cd 100644
--- a/CHANGES
+++ b/CHANGES
@@ -10,6 +10,7 @@ OpenLDAP 2.4.18 Engineering
 	Added slapd tcp buffers support (ITS#6234)
 	Fixed slapd allow mirrormode to be set to FALSE (ITS#5946)
 	Fixed slapd certificate list parsing (ITS#6241)
+	Fixed slapd writers blocking (ITS#6276)
 	Fixed slapd dncachesize behavior to unlimited by default (ITS#6222)
 	Fixed slapd incorrectly applying writetimeout when not set (ITS#6220)
 	Fixed slapd with duplicate empty lines for olcDbConfig (ITS#6240)
diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c
index b8c7cf05d7..e1f651bd2b 100644
--- a/servers/slapd/connection.c
+++ b/servers/slapd/connection.c
@@ -753,6 +753,32 @@ static void connection_abandon( Connection *c )
 	}
 }
 
+static void
+connection_wake_writers( Connection *c )
+{
+	/* wake write blocked operations */
+	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 );
+	}
+}
+
 void connection_closing( Connection *c, const char *why )
 {
 	assert( connections != NULL );
@@ -777,26 +803,7 @@ void connection_closing( Connection *c, const char *why )
 		connection_abandon( c );
 
 		/* wake write blocked operations */
-		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 );
-		}
+		connection_wake_writers( c );
 
 	} else if( why == NULL && c->c_close_reason == conn_lost_str ) {
 		/* Client closed connection after doing Unbind. */
@@ -1270,6 +1277,11 @@ int connection_read_activate( ber_socket_t s )
 	if ( rc )
 		return rc;
 
+	/* Don't let blocked writers block a pause request */
+	if ( connections[s].c_writewaiter &&
+		ldap_pvt_thread_pool_pausing( &connection_pool ))
+		connection_wake_writers( &connections[s] );
+
 	rc = ldap_pvt_thread_pool_submit( &connection_pool,
 		connection_read_thread, (void *)(long)s );
 
-- 
GitLab