Handle a client connection disconnected from op

This commit is contained in:
Ondřej Kuzník 2017-07-11 13:08:21 +01:00 committed by Ondřej Kuzník
parent d4225924bc
commit 6140cdf6f8
3 changed files with 30 additions and 28 deletions

View file

@ -263,7 +263,6 @@ void
client_reset( Connection *c )
{
TAvlnode *root;
int freed;
root = c->c_ops;
c->c_ops = NULL;
@ -292,19 +291,8 @@ client_reset( Connection *c )
CONNECTION_UNLOCK_INCREF(c);
if ( root ) {
TAvlnode *node = tavl_end( root, TAVL_DIR_LEFT );
do {
Operation *op = node->avl_data;
operation_abandon( op );
CONNECTION_LOCK(c);
op->o_client_refcnt--;
operation_destroy_from_client( op );
CONNECTION_UNLOCK(c);
} while ( (node = tavl_next( node, TAVL_DIR_RIGHT )) );
freed = tavl_free( root, NULL );
int freed;
freed = tavl_free( root, (AVL_FREE)operation_abandon );
Debug( LDAP_DEBUG_TRACE, "client_reset: "
"dropped %d operations\n",
freed );

View file

@ -513,6 +513,13 @@ fail:
return NULL;
}
/*
* Will remove the operation from its upstream and if it was still there,
* sends an abandon request.
*
* Being called from client_reset or request_abandon, the following hold:
* - op->o_client_refcnt > 0 (and it follows that op->o_client != NULL)
*/
void
operation_abandon( Operation *op )
{
@ -524,22 +531,15 @@ operation_abandon( Operation *op )
ldap_pvt_thread_mutex_lock( &operation_mutex );
c = op->o_upstream;
if ( !c ) {
c = op->o_client;
assert( c );
/* Caller should hold a reference on client */
CONNECTION_LOCK(c);
ldap_pvt_thread_mutex_unlock( &operation_mutex );
operation_destroy_from_client( op );
CLIENT_UNLOCK_OR_DESTROY(c);
return;
goto done;
}
CONNECTION_LOCK(c);
ldap_pvt_thread_mutex_unlock( &operation_mutex );
if ( tavl_delete( &c->c_ops, op, operation_upstream_cmp ) == NULL ) {
/* The operation has already been abandoned or finished */
goto done;
goto unlock;
}
c->c_n_ops_executing--;
b = (Backend *)c->c_private;
@ -557,7 +557,7 @@ operation_abandon( Operation *op )
"ber_alloc failed\n" );
ldap_pvt_thread_mutex_unlock( &c->c_io_mutex );
CONNECTION_LOCK_DECREF(c);
goto done;
goto unlock;
}
c->c_pendingber = ber;
@ -577,9 +577,18 @@ operation_abandon( Operation *op )
}
CONNECTION_LOCK_DECREF(c);
done:
operation_destroy_from_upstream( op );
unlock:
UPSTREAM_UNLOCK_OR_DESTROY(c);
done:
c = op->o_client;
assert( c );
/* Caller should hold a reference on client */
CONNECTION_LOCK(c);
op->o_client_refcnt--;
operation_destroy_from_client( op );
CONNECTION_UNLOCK(c);
}
int

View file

@ -418,8 +418,13 @@ handle_one_response( Connection *c )
client = op->o_client;
if ( client ) {
CONNECTION_LOCK(client);
op->o_client_refcnt++;
CONNECTION_UNLOCK_INCREF(client);
if ( client->c_live ) {
op->o_client_refcnt++;
CONNECTION_UNLOCK_INCREF(client);
} else {
CONNECTION_UNLOCK(client);
client = NULL;
}
}
ldap_pvt_thread_mutex_unlock( &operation_mutex );