Commit b017dc9b authored by Quanah Gibson-Mount's avatar Quanah Gibson-Mount
Browse files

ITS#5835, ITS#5886

parent 6cadcfe3
......@@ -11,6 +11,8 @@ OpenLDAP 2.4.14 Engineering
Added slapo-rwm newRDN rewriting (ITS#5834)
Fixed slapd bconfig to return error codes (ITS#5867)
Fixed slapd bconfig encoding incorrectly (ITS#5897)
Fixed slapd connection assert (ITS#5835)
Fixed slapd epoll handling (ITS#5886)
Fixed slapd syncrepl rename handling (ITS#5809)
Fixed slapd syncrepl MMR when adding new server (ITS#5850)
Fixed slapd syncrepl replication with glued DB (ITS#5866)
......
......@@ -163,8 +163,10 @@ int connections_destroy(void)
if( connections[i].c_struct_state != SLAP_C_UNINITIALIZED ) {
ber_sockbuf_free( connections[i].c_sb );
ldap_pvt_thread_mutex_destroy( &connections[i].c_mutex );
ldap_pvt_thread_mutex_destroy( &connections[i].c_write_mutex );
ldap_pvt_thread_cond_destroy( &connections[i].c_write_cv );
ldap_pvt_thread_mutex_destroy( &connections[i].c_write1_mutex );
ldap_pvt_thread_mutex_destroy( &connections[i].c_write2_mutex );
ldap_pvt_thread_cond_destroy( &connections[i].c_write1_cv );
ldap_pvt_thread_cond_destroy( &connections[i].c_write2_cv );
#ifdef LDAP_SLAPI
if ( slapi_plugins_used ) {
slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION,
......@@ -384,8 +386,10 @@ Connection * connection_init(
/* should check status of thread calls */
ldap_pvt_thread_mutex_init( &c->c_mutex );
ldap_pvt_thread_mutex_init( &c->c_write_mutex );
ldap_pvt_thread_cond_init( &c->c_write_cv );
ldap_pvt_thread_mutex_init( &c->c_write1_mutex );
ldap_pvt_thread_mutex_init( &c->c_write2_mutex );
ldap_pvt_thread_cond_init( &c->c_write1_cv );
ldap_pvt_thread_cond_init( &c->c_write2_cv );
#ifdef LDAP_SLAPI
if ( slapi_plugins_used ) {
......@@ -417,6 +421,7 @@ Connection * connection_init(
assert( c->c_sasl_bindop == NULL );
assert( c->c_currentber == NULL );
assert( c->c_writewaiter == 0);
assert( c->c_writers == 0);
c->c_listener = listener;
c->c_sd = s;
......@@ -593,6 +598,7 @@ connection_destroy( Connection *c )
assert( LDAP_STAILQ_EMPTY(&c->c_txn_ops) );
#endif
assert( c->c_writewaiter == 0);
assert( c->c_writers == 0);
/* only for stats (print -1 as "%lu" may give unexpected results ;) */
connid = c->c_connid;
......@@ -752,18 +758,24 @@ void connection_closing( Connection *c, const char *why )
connection_abandon( c );
/* wake write blocked operations */
if ( c->c_writewaiter ) {
ldap_pvt_thread_cond_signal( &c->c_write_cv );
/* ITS#4667 this may allow another thread to drop into
* connection_resched / connection_close before we
* finish, but that's OK.
*/
slapd_clr_write( c->c_sd, 1 );
ldap_pvt_thread_mutex_unlock( &c->c_mutex );
ldap_pvt_thread_mutex_lock( &c->c_write_mutex );
ldap_pvt_thread_mutex_lock( &c->c_mutex );
ldap_pvt_thread_mutex_unlock( &c->c_write_mutex );
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 );
}
......@@ -778,11 +790,6 @@ connection_close( Connection *c )
{
assert( connections != NULL );
assert( c != NULL );
/* ITS#4667 we may have gotten here twice */
if ( c->c_conn_state == SLAP_C_INVALID )
return;
assert( c->c_struct_state == SLAP_C_USED );
assert( c->c_conn_state == SLAP_C_CLOSING );
......@@ -1174,7 +1181,7 @@ void connection_client_stop(
/* get (locked) connection */
c = connection_get( s );
assert( c->c_conn_state == SLAP_C_CLIENT );
c->c_listener = NULL;
......@@ -1246,6 +1253,24 @@ int connection_read_activate( ber_socket_t s )
return rc;
}
void
connection_hangup( ber_socket_t s )
{
Connection *c;
c = connection_get( s );
if ( c ) {
if ( c->c_conn_state == SLAP_C_CLIENT ) {
connection_return( c );
connection_read_activate( s );
} else {
connection_closing( c, "connection lost" );
connection_close( c );
connection_return( c );
}
}
}
static int
connection_read( ber_socket_t s, conn_readinfo *cri )
{
......@@ -1831,7 +1856,7 @@ int connection_write(ber_socket_t s)
Debug( LDAP_DEBUG_TRACE,
"connection_write(%d): waking output for id=%lu\n",
s, c->c_connid, 0 );
ldap_pvt_thread_cond_signal( &c->c_write_cv );
ldap_pvt_thread_cond_signal( &c->c_write2_cv );
if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) ) {
slapd_set_read( s, 1 );
......
......@@ -2495,7 +2495,7 @@ slapd_daemon_task(
#endif /* LDAP_DEBUG */
for ( i = 0; i < ns; i++ ) {
int rc = 1, fd;
int rc = 1, fd, w = 0;
if ( SLAP_EVENT_IS_LISTENER( i ) ) {
rc = slap_listener_activate( SLAP_EVENT_LISTENER( i ) );
......@@ -2522,6 +2522,7 @@ slapd_daemon_task(
fd, 0, 0 );
SLAP_EVENT_CLR_WRITE( i );
w = 1;
/*
* NOTE: it is possible that the connection was closed
......@@ -2541,9 +2542,10 @@ slapd_daemon_task(
SLAP_EVENT_CLR_READ( i );
connection_read_activate( fd );
} else {
} else if ( !w ) {
Debug( LDAP_DEBUG_CONNS,
"daemon: hangup on %d\n", fd, 0, 0 );
connection_hangup( fd );
}
}
}
......
......@@ -745,6 +745,7 @@ LDAP_SLAPD_F (Connection *) connection_init LDAP_P((
LDAP_SLAPD_F (void) connection_closing LDAP_P((
Connection *c, const char *why ));
LDAP_SLAPD_F (void) connection_hangup LDAP_P(( ber_socket_t fd ));
LDAP_SLAPD_F (int) connection_state_closing LDAP_P(( Connection *c ));
LDAP_SLAPD_F (const char *) connection_state2str LDAP_P(( int state ))
LDAP_GCCATTR((const));
......
......@@ -137,27 +137,44 @@ static long send_ldap_ber(
BerElement *ber )
{
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_write_mutex );
ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
if ( connection_state_closing( conn )) {
ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
return 0;
}
while ( conn->c_writers > 0 ) {
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 );
}
/* lock the connection */
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
conn->c_writers++;
ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
if ( closing )
return 0;
/* write the pdu */
while( 1 ) {
int err;
if ( connection_state_closing( conn ) ) {
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
return 0;
}
/* lock the connection */
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
if ( ber_flush2( conn->c_sb, ber, LBER_FLUSH_FREE_NEVER ) == 0 ) {
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
ret = bytes;
break;
}
......@@ -176,23 +193,41 @@ static long send_ldap_ber(
connection_closing( conn, "connection lost on write" );
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
return( -1 );
ret = -1;
break;
}
/* wait for socket to be write-ready */
ldap_pvt_thread_mutex_lock( &conn->c_write2_mutex );
conn->c_writewaiter = 1;
slapd_set_write( conn->c_sd, 1 );
ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
ldap_pvt_thread_cond_wait( &conn->c_write2_cv, &conn->c_write2_mutex );
conn->c_writewaiter = 0;
ldap_pvt_thread_mutex_unlock( &conn->c_write2_mutex );
ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
closing = ( conn->c_writers < 0 );
ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
if ( closing ) {
ret = 0;
break;
}
}
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
if ( conn->c_writers < 0 ) {
conn->c_writers++;
if ( !conn->c_writers )
ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
} else {
conn->c_writers--;
ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
}
ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
return bytes;
return ret;
}
static int
......
......@@ -2801,14 +2801,17 @@ struct Connection {
LDAP_STAILQ_HEAD(c_o, Operation) c_ops; /* list of operations being processed */
LDAP_STAILQ_HEAD(c_po, Operation) c_pending_ops; /* list of pending operations */
ldap_pvt_thread_mutex_t c_write_mutex; /* only one pdu written at a time */
ldap_pvt_thread_cond_t c_write_cv; /* used to wait for sd write-ready*/
ldap_pvt_thread_mutex_t c_write1_mutex; /* only one pdu written at a time */
ldap_pvt_thread_cond_t c_write1_cv; /* only one pdu written at a time */
ldap_pvt_thread_mutex_t c_write2_mutex; /* used to wait for sd write-ready */
ldap_pvt_thread_cond_t c_write2_cv; /* used to wait for sd write-ready*/
BerElement *c_currentber; /* ber we're attempting to read */
int c_writers; /* number of writers waiting */
char c_sasl_bind_in_progress; /* multi-op bind in progress */
char c_writewaiter; /* true if blocked on write */
char c_writewaiter; /* true if writer is waiting */
#define CONN_IS_TLS 1
#define CONN_IS_UDP 2
......
......@@ -224,8 +224,10 @@ slapi_int_connection_init_pb( Slapi_PBlock *pb, ber_tag_t tag )
/* should check status of thread calls */
ldap_pvt_thread_mutex_init( &conn->c_mutex );
ldap_pvt_thread_mutex_init( &conn->c_write_mutex );
ldap_pvt_thread_cond_init( &conn->c_write_cv );
ldap_pvt_thread_mutex_init( &conn->c_write1_mutex );
ldap_pvt_thread_mutex_init( &conn->c_write2_mutex );
ldap_pvt_thread_cond_init( &conn->c_write1_cv );
ldap_pvt_thread_cond_init( &conn->c_write2_cv );
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment