fix potential deadlock; first round of refcnt for connections

This commit is contained in:
Pierangelo Masarati 2005-07-03 23:28:35 +00:00
parent 982981d465
commit 9146b262ad
3 changed files with 57 additions and 20 deletions

View File

@ -177,6 +177,7 @@ typedef struct metasingleconn_t {
typedef struct metaconn_t { typedef struct metaconn_t {
struct slap_conn *mc_conn; struct slap_conn *mc_conn;
ldap_pvt_thread_mutex_t mc_mutex; ldap_pvt_thread_mutex_t mc_mutex;
unsigned mc_refcnt;
/* /*
* means that the connection is bound; * means that the connection is bound;
@ -186,7 +187,10 @@ typedef struct metaconn_t {
#define META_BOUND_NONE (-1) #define META_BOUND_NONE (-1)
#define META_BOUND_ALL (-2) #define META_BOUND_ALL (-2)
/* supersedes the connection stuff */ /* 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; } metaconn_t;
typedef struct metatarget_t { typedef struct metatarget_t {

View File

@ -24,6 +24,7 @@
#include <stdio.h> #include <stdio.h>
#include <ac/errno.h>
#include <ac/socket.h> #include <ac/socket.h>
#include <ac/string.h> #include <ac/string.h>
@ -136,8 +137,6 @@ metaconn_alloc(
return NULL; return NULL;
} }
mc->mc_conns = ( metasingleconn_t * )&mc[ 1 ];
for ( i = 0; i < ntargets; i++ ) { for ( i = 0; i < ntargets; i++ ) {
mc->mc_conns[ i ].msc_ld = NULL; mc->mc_conns[ i ].msc_ld = NULL;
BER_BVZERO( &mc->mc_conns[ i ].msc_bound_ndn ); BER_BVZERO( &mc->mc_conns[ i ].msc_bound_ndn );
@ -148,6 +147,7 @@ metaconn_alloc(
mc->mc_auth_target = META_BOUND_NONE; mc->mc_auth_target = META_BOUND_NONE;
ldap_pvt_thread_mutex_init( &mc->mc_mutex ); ldap_pvt_thread_mutex_init( &mc->mc_mutex );
mc->mc_refcnt = 1;
return mc; return mc;
} }
@ -626,7 +626,16 @@ meta_back_getconn(
/* Searches for a metaconn in the avl tree */ /* Searches for a metaconn in the avl tree */
mc_curr.mc_conn = op->o_conn; 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, mc = (metaconn_t *)avl_find( mi->mi_conntree,
(caddr_t)&mc_curr, meta_back_conn_cmp ); (caddr_t)&mc_curr, meta_back_conn_cmp );
ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex ); 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 */ /* Retries searching for a metaconn in the avl tree */
mc_curr.mc_conn = op->o_conn; 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, mc = (metaconn_t *)avl_find( mi->mi_conntree,
(caddr_t)&mc_curr, meta_back_conn_cmp ); (caddr_t)&mc_curr, meta_back_conn_cmp );
ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex ); 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 ], err = meta_back_init_one_conn( op, rs, &mi->mi_targets[ i ],
&mc->mc_conns[ i ], sendok ); &mc->mc_conns[ i ], sendok );
if ( err == LDAP_SUCCESS ) { if ( err != LDAP_SUCCESS ) {
candidates[ i ].sr_tag = META_CANDIDATE;
ncandidates++;
} else {
/* /*
* FIXME: in case one target cannot * FIXME: in case one target cannot
* be init'd, should the other ones * be init'd, should the other ones
@ -829,6 +842,9 @@ meta_back_getconn(
return NULL; return NULL;
} }
candidates[ i ].sr_tag = META_CANDIDATE;
ncandidates++;
if ( candidate ) { if ( candidate ) {
*candidate = i; *candidate = i;
} }
@ -923,7 +939,16 @@ done:;
/* /*
* Inserts the newly created metaconn in the avl tree * 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, err = avl_insert( &mi->mi_conntree, ( caddr_t )mc,
meta_back_conn_cmp, meta_back_conn_dup ); meta_back_conn_cmp, meta_back_conn_dup );
@ -936,12 +961,7 @@ done:;
/* /*
* Err could be -1 in case a duplicate metaconn is inserted * Err could be -1 in case a duplicate metaconn is inserted
*/ */
if ( err == 0 ) { 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 {
Debug( LDAP_DEBUG_ANY, Debug( LDAP_DEBUG_ANY,
"%s meta_back_getconn: candidates=%d conn=%ld insert failed\n", "%s meta_back_getconn: candidates=%d conn=%ld insert failed\n",
op->o_log_prefix, ncandidates, mc->mc_conn->c_connid ); op->o_log_prefix, ncandidates, mc->mc_conn->c_connid );
@ -956,6 +976,10 @@ done:;
return NULL; 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 { } else {
Debug( LDAP_DEBUG_TRACE, Debug( LDAP_DEBUG_TRACE,
"%s meta_back_getconn: candidates=%d conn=%ld fetched\n", "%s meta_back_getconn: candidates=%d conn=%ld fetched\n",

View File

@ -24,9 +24,9 @@
#include <stdio.h> #include <stdio.h>
#include <ac/errno.h>
#include <ac/socket.h> #include <ac/socket.h>
#include <ac/string.h> #include <ac/string.h>
#include <ac/errno.h>
#include "slap.h" #include "slap.h"
#include "../back-ldap/back-ldap.h" #include "../back-ldap/back-ldap.h"
@ -47,7 +47,16 @@ meta_back_conn_destroy(
mc_curr.mc_conn = conn; 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, mc = avl_delete( &mi->mi_conntree, ( caddr_t )&mc_curr,
meta_back_conn_cmp ); meta_back_conn_cmp );
ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex ); ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );