Commit 7b7f9724 authored by Ondřej Kuzník's avatar Ondřej Kuzník Committed by Ondřej Kuzník
Browse files

Avoid a deadlock with client

parent 7b413f9e
......@@ -358,6 +358,7 @@ void
client_destroy( Connection *c )
{
enum sc_state state;
struct event *read_event, *write_event;
Debug( LDAP_DEBUG_CONNS, "client_destroy: "
"destroying client connid=%lu\n",
......@@ -367,14 +368,27 @@ client_destroy( Connection *c )
state = c->c_state;
c->c_state = SLAP_C_INVALID;
if ( c->c_read_event ) {
event_free( c->c_read_event );
c->c_read_event = NULL;
read_event = c->c_read_event;
write_event = c->c_write_event;
/*
* FIXME: operation_destroy_from_upstream might copy op->o_client and bump
* c_refcnt, it is then responsible to call destroy_client again, does that
* mean that we can be triggered for recursion over all connections?
*/
CONNECTION_UNLOCK_INCREF(c);
/*
* Avoid a deadlock:
* event_del will block if the event is currently executing its callback,
* that callback might be waiting to lock c->c_mutex
*/
if ( read_event ) {
event_del( read_event );
}
if ( c->c_write_event ) {
event_free( c->c_write_event );
c->c_write_event = NULL;
if ( write_event ) {
event_del( write_event );
}
if ( state != SLAP_C_CLOSING ) {
......@@ -383,6 +397,18 @@ client_destroy( Connection *c )
ldap_pvt_thread_mutex_unlock( &clients_mutex );
}
CONNECTION_LOCK_DECREF(c);
if ( c->c_read_event ) {
event_free( c->c_read_event );
c->c_read_event = NULL;
}
if ( c->c_write_event ) {
event_free( c->c_write_event );
c->c_write_event = NULL;
}
client_reset( c );
/*
......
Supports Markdown
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