mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-24 00:29:35 -05:00
Another attempt at operation/connection destroy interaction.
This commit is contained in:
parent
26f721510a
commit
1dfeca3539
2 changed files with 64 additions and 40 deletions
|
|
@ -161,17 +161,20 @@ operation_destroy_from_client( Operation *op )
|
|||
/* 2. Remove from the operation map and TODO adjust the pending op count */
|
||||
tavl_delete( &client->c_ops, op, operation_client_cmp );
|
||||
|
||||
CONNECTION_UNLOCK_INCREF(client);
|
||||
|
||||
/* 3. Detect whether we entered a race to free op and indicate that to any
|
||||
* others */
|
||||
ldap_pvt_thread_mutex_lock( &operation_mutex );
|
||||
ldap_pvt_thread_mutex_lock( &op->o_mutex );
|
||||
race_state = op->o_freeing;
|
||||
op->o_freeing |= SLAP_OP_FREEING_CLIENT;
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_mutex );
|
||||
|
||||
CONNECTION_UNLOCK_INCREF(client);
|
||||
|
||||
if ( detach_client ) {
|
||||
ldap_pvt_thread_mutex_lock( &operation_mutex );
|
||||
op->o_client = NULL;
|
||||
ldap_pvt_thread_mutex_unlock( &operation_mutex );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &operation_mutex );
|
||||
|
||||
/* 4. If we lost the race, deal with it */
|
||||
if ( race_state ) {
|
||||
|
|
@ -181,10 +184,10 @@ operation_destroy_from_client( Operation *op )
|
|||
* other side has finished (it knows we did that when it examines
|
||||
* o_freeing again).
|
||||
*/
|
||||
if ( race_state == SLAP_OP_FREEING_UPSTREAM ) {
|
||||
if ( !detach_client && race_state == SLAP_OP_FREEING_UPSTREAM ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "operation_destroy_from_client: "
|
||||
"op=%p lost race, increasing client refcnt\n",
|
||||
op );
|
||||
"op=%p lost race, increasing client refcnt c=%p\n",
|
||||
op, client );
|
||||
CONNECTION_LOCK(client);
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_TRACE, "operation_destroy_from_client: "
|
||||
|
|
@ -200,19 +203,24 @@ operation_destroy_from_client( Operation *op )
|
|||
ldap_pvt_thread_mutex_lock( &operation_mutex );
|
||||
upstream = op->o_upstream;
|
||||
if ( upstream ) {
|
||||
if ( op->o_freeing & SLAP_OP_FREEING_UPSTREAM ) {
|
||||
/*
|
||||
* We have raced to destroy op and won. To avoid freeing the connection
|
||||
* under us, a refcnt token has been left over for us on the upstream,
|
||||
* decref and see whether we are in charge of freeing it
|
||||
*/
|
||||
CONNECTION_LOCK_DECREF(upstream);
|
||||
} else {
|
||||
CONNECTION_LOCK(upstream);
|
||||
}
|
||||
CONNECTION_LOCK(upstream);
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &operation_mutex );
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &op->o_mutex );
|
||||
if ( upstream && ( op->o_freeing & SLAP_OP_FREEING_UPSTREAM ) ) {
|
||||
/*
|
||||
* We have raced to destroy op and won. To avoid freeing the connection
|
||||
* under us, a refcnt token has been left over for us on the upstream,
|
||||
* decref and see whether we are in charge of freeing it
|
||||
*/
|
||||
upstream->c_refcnt--;
|
||||
Debug( LDAP_DEBUG_TRACE, "operation_destroy_from_client: "
|
||||
"op=%p other side lost race with us\n",
|
||||
op );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_mutex );
|
||||
|
||||
/* 6. liveness/refcnt adjustment and test */
|
||||
op->o_upstream_refcnt -= op->o_upstream_live;
|
||||
op->o_upstream_live = 0;
|
||||
|
|
@ -220,13 +228,15 @@ operation_destroy_from_client( Operation *op )
|
|||
Debug( LDAP_DEBUG_TRACE, "operation_destroy_from_client: "
|
||||
"op=%p other side still alive, refcnt=%d\n",
|
||||
op, op->o_upstream_refcnt );
|
||||
|
||||
/* There must have been no race if op is still alive */
|
||||
assert( upstream != NULL );
|
||||
CONNECTION_UNLOCK(upstream);
|
||||
ldap_pvt_thread_mutex_lock( &operation_mutex );
|
||||
ldap_pvt_thread_mutex_lock( &op->o_mutex );
|
||||
op->o_freeing &= ~SLAP_OP_FREEING_CLIENT;
|
||||
assert( op->o_freeing == 0 );
|
||||
ldap_pvt_thread_mutex_unlock( &operation_mutex );
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_mutex );
|
||||
|
||||
assert( upstream != NULL );
|
||||
CONNECTION_UNLOCK(upstream);
|
||||
CONNECTION_LOCK_DECREF(client);
|
||||
return;
|
||||
}
|
||||
|
|
@ -252,6 +262,7 @@ operation_destroy_from_client( Operation *op )
|
|||
"client msgid=%d\n",
|
||||
op, op->o_client_connid, op->o_client_msgid );
|
||||
ber_free( op->o_ber, 1 );
|
||||
ldap_pvt_thread_mutex_destroy( &op->o_mutex );
|
||||
ch_free( op );
|
||||
|
||||
CONNECTION_LOCK_DECREF(client);
|
||||
|
|
@ -289,12 +300,15 @@ operation_destroy_from_upstream( Operation *op )
|
|||
b = (Backend *)upstream->c_private;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &op->o_mutex );
|
||||
race_state = op->o_freeing;
|
||||
op->o_freeing |= SLAP_OP_FREEING_UPSTREAM;
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_mutex );
|
||||
|
||||
CONNECTION_UNLOCK_INCREF(upstream);
|
||||
|
||||
/* 3. Detect whether we entered a race to free op */
|
||||
ldap_pvt_thread_mutex_lock( &operation_mutex );
|
||||
race_state = op->o_freeing;
|
||||
op->o_freeing |= SLAP_OP_FREEING_UPSTREAM;
|
||||
if ( detach_upstream ) {
|
||||
op->o_upstream = NULL;
|
||||
}
|
||||
|
|
@ -314,10 +328,10 @@ operation_destroy_from_upstream( Operation *op )
|
|||
* other side has finished (it knows we did that when it examines
|
||||
* o_freeing again).
|
||||
*/
|
||||
if ( race_state == SLAP_OP_FREEING_CLIENT ) {
|
||||
if ( !detach_upstream && race_state == SLAP_OP_FREEING_CLIENT ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "operation_destroy_from_upstream: "
|
||||
"op=%p lost race, increased client refcnt\n",
|
||||
op );
|
||||
"op=%p lost race, increasing upstream refcnt c=%p\n",
|
||||
op, upstream );
|
||||
CONNECTION_LOCK(upstream);
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_TRACE, "operation_destroy_from_upstream: "
|
||||
|
|
@ -333,19 +347,24 @@ operation_destroy_from_upstream( Operation *op )
|
|||
ldap_pvt_thread_mutex_lock( &operation_mutex );
|
||||
client = op->o_client;
|
||||
if ( client ) {
|
||||
if ( op->o_freeing & SLAP_OP_FREEING_CLIENT ) {
|
||||
/*
|
||||
* We have raced to destroy op and won. To avoid freeing the connection
|
||||
* under us, a refcnt token has been left over for us on the client,
|
||||
* decref and see whether we are in charge of freeing it
|
||||
*/
|
||||
CONNECTION_LOCK_DECREF(client);
|
||||
} else {
|
||||
CONNECTION_LOCK(client);
|
||||
}
|
||||
CONNECTION_LOCK(client);
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &operation_mutex );
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &op->o_mutex );
|
||||
if ( client && ( op->o_freeing & SLAP_OP_FREEING_CLIENT ) ) {
|
||||
/*
|
||||
* We have raced to destroy op and won. To avoid freeing the connection
|
||||
* under us, a refcnt token has been left over for us on the client,
|
||||
* decref and see whether we are in charge of freeing it
|
||||
*/
|
||||
client->c_refcnt--;
|
||||
Debug( LDAP_DEBUG_TRACE, "operation_destroy_from_upstream: "
|
||||
"op=%p other side lost race with us\n",
|
||||
op );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_mutex );
|
||||
|
||||
/* 6. liveness/refcnt adjustment and test */
|
||||
op->o_client_refcnt -= op->o_client_live;
|
||||
op->o_client_live = 0;
|
||||
|
|
@ -354,12 +373,13 @@ operation_destroy_from_upstream( Operation *op )
|
|||
"op=%p other side still alive, refcnt=%d\n",
|
||||
op, op->o_client_refcnt );
|
||||
/* There must have been no race if op is still alive */
|
||||
assert( client != NULL );
|
||||
CONNECTION_UNLOCK(client);
|
||||
ldap_pvt_thread_mutex_lock( &operation_mutex );
|
||||
ldap_pvt_thread_mutex_lock( &op->o_mutex );
|
||||
op->o_freeing &= ~SLAP_OP_FREEING_UPSTREAM;
|
||||
assert( op->o_freeing == 0 );
|
||||
ldap_pvt_thread_mutex_unlock( &operation_mutex );
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_mutex );
|
||||
|
||||
assert( client != NULL );
|
||||
CONNECTION_UNLOCK(client);
|
||||
CONNECTION_LOCK_DECREF(upstream);
|
||||
return;
|
||||
}
|
||||
|
|
@ -376,6 +396,7 @@ operation_destroy_from_upstream( Operation *op )
|
|||
"client msgid=%d\n",
|
||||
op, op->o_client_connid, op->o_client_msgid );
|
||||
ber_free( op->o_ber, 1 );
|
||||
ldap_pvt_thread_mutex_destroy( &op->o_mutex );
|
||||
ch_free( op );
|
||||
|
||||
CONNECTION_LOCK_DECREF(upstream);
|
||||
|
|
@ -397,6 +418,8 @@ operation_init( Connection *c, BerElement *ber )
|
|||
op->o_client_connid = c->c_connid;
|
||||
op->o_ber = ber;
|
||||
|
||||
ldap_pvt_thread_mutex_init( &op->o_mutex );
|
||||
|
||||
op->o_client_live = op->o_client_refcnt = 1;
|
||||
op->o_upstream_live = op->o_upstream_refcnt = 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -423,6 +423,7 @@ struct Operation {
|
|||
int o_upstream_live, o_upstream_refcnt;
|
||||
ber_int_t o_upstream_msgid;
|
||||
|
||||
ldap_pvt_thread_mutex_t o_mutex;
|
||||
enum op_state o_freeing;
|
||||
ber_tag_t o_tag;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue