mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
fix potential deadlock; first round of refcnt for connections
This commit is contained in:
parent
982981d465
commit
9146b262ad
@ -177,6 +177,7 @@ typedef struct metasingleconn_t {
|
||||
typedef struct metaconn_t {
|
||||
struct slap_conn *mc_conn;
|
||||
ldap_pvt_thread_mutex_t mc_mutex;
|
||||
unsigned mc_refcnt;
|
||||
|
||||
/*
|
||||
* means that the connection is bound;
|
||||
@ -186,7 +187,10 @@ typedef struct metaconn_t {
|
||||
#define META_BOUND_NONE (-1)
|
||||
#define META_BOUND_ALL (-2)
|
||||
/* supersedes the connection stuff */
|
||||
metasingleconn_t *mc_conns;
|
||||
metasingleconn_t mc_conns[ 1 ];
|
||||
/* NOTE: mc_conns must be last, because
|
||||
* the required number of conns is malloc'ed
|
||||
* in one block with the metaconn_t structure */
|
||||
} metaconn_t;
|
||||
|
||||
typedef struct metatarget_t {
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/errno.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
@ -136,8 +137,6 @@ metaconn_alloc(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mc->mc_conns = ( metasingleconn_t * )&mc[ 1 ];
|
||||
|
||||
for ( i = 0; i < ntargets; i++ ) {
|
||||
mc->mc_conns[ i ].msc_ld = NULL;
|
||||
BER_BVZERO( &mc->mc_conns[ i ].msc_bound_ndn );
|
||||
@ -148,6 +147,7 @@ metaconn_alloc(
|
||||
|
||||
mc->mc_auth_target = META_BOUND_NONE;
|
||||
ldap_pvt_thread_mutex_init( &mc->mc_mutex );
|
||||
mc->mc_refcnt = 1;
|
||||
|
||||
return mc;
|
||||
}
|
||||
@ -626,7 +626,16 @@ meta_back_getconn(
|
||||
|
||||
/* Searches for a metaconn in the avl tree */
|
||||
mc_curr.mc_conn = op->o_conn;
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
|
||||
retry_lock:;
|
||||
switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
|
||||
case LDAP_PVT_THREAD_EBUSY:
|
||||
default:
|
||||
ldap_pvt_thread_yield();
|
||||
goto retry_lock;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
mc = (metaconn_t *)avl_find( mi->mi_conntree,
|
||||
(caddr_t)&mc_curr, meta_back_conn_cmp );
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
|
||||
@ -786,7 +795,16 @@ meta_back_getconn(
|
||||
|
||||
/* Retries searching for a metaconn in the avl tree */
|
||||
mc_curr.mc_conn = op->o_conn;
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
|
||||
retry_lock2:;
|
||||
switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
|
||||
case LDAP_PVT_THREAD_EBUSY:
|
||||
default:
|
||||
ldap_pvt_thread_yield();
|
||||
goto retry_lock2;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
mc = (metaconn_t *)avl_find( mi->mi_conntree,
|
||||
(caddr_t)&mc_curr, meta_back_conn_cmp );
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
|
||||
@ -810,12 +828,7 @@ meta_back_getconn(
|
||||
*/
|
||||
err = meta_back_init_one_conn( op, rs, &mi->mi_targets[ i ],
|
||||
&mc->mc_conns[ i ], sendok );
|
||||
if ( err == LDAP_SUCCESS ) {
|
||||
candidates[ i ].sr_tag = META_CANDIDATE;
|
||||
ncandidates++;
|
||||
|
||||
} else {
|
||||
|
||||
if ( err != LDAP_SUCCESS ) {
|
||||
/*
|
||||
* FIXME: in case one target cannot
|
||||
* be init'd, should the other ones
|
||||
@ -829,6 +842,9 @@ meta_back_getconn(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
candidates[ i ].sr_tag = META_CANDIDATE;
|
||||
ncandidates++;
|
||||
|
||||
if ( candidate ) {
|
||||
*candidate = i;
|
||||
}
|
||||
@ -923,7 +939,16 @@ done:;
|
||||
/*
|
||||
* Inserts the newly created metaconn in the avl tree
|
||||
*/
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
|
||||
retry_lock3:;
|
||||
switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
|
||||
case LDAP_PVT_THREAD_EBUSY:
|
||||
default:
|
||||
ldap_pvt_thread_yield();
|
||||
goto retry_lock3;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
err = avl_insert( &mi->mi_conntree, ( caddr_t )mc,
|
||||
meta_back_conn_cmp, meta_back_conn_dup );
|
||||
|
||||
@ -936,12 +961,7 @@ done:;
|
||||
/*
|
||||
* Err could be -1 in case a duplicate metaconn is inserted
|
||||
*/
|
||||
if ( err == 0 ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"%s meta_back_getconn: candidates=%d conn=%ld inserted\n",
|
||||
op->o_log_prefix, ncandidates, mc->mc_conn->c_connid );
|
||||
|
||||
} else {
|
||||
if ( err != 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s meta_back_getconn: candidates=%d conn=%ld insert failed\n",
|
||||
op->o_log_prefix, ncandidates, mc->mc_conn->c_connid );
|
||||
@ -956,6 +976,10 @@ done:;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"%s meta_back_getconn: candidates=%d conn=%ld inserted\n",
|
||||
op->o_log_prefix, ncandidates, mc->mc_conn->c_connid );
|
||||
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"%s meta_back_getconn: candidates=%d conn=%ld fetched\n",
|
||||
|
@ -24,9 +24,9 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/errno.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/errno.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
@ -47,7 +47,16 @@ meta_back_conn_destroy(
|
||||
|
||||
mc_curr.mc_conn = conn;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
|
||||
retry_lock:;
|
||||
switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
|
||||
case LDAP_PVT_THREAD_EBUSY:
|
||||
default:
|
||||
ldap_pvt_thread_yield();
|
||||
goto retry_lock;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
mc = avl_delete( &mi->mi_conntree, ( caddr_t )&mc_curr,
|
||||
meta_back_conn_cmp );
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
|
||||
|
Loading…
Reference in New Issue
Block a user