From 9146b262ad8a31dab8a4cf1b993897b2614a00b3 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Sun, 3 Jul 2005 23:28:35 +0000 Subject: [PATCH] fix potential deadlock; first round of refcnt for connections --- servers/slapd/back-meta/back-meta.h | 6 ++- servers/slapd/back-meta/conn.c | 58 ++++++++++++++++++++--------- servers/slapd/back-meta/unbind.c | 13 ++++++- 3 files changed, 57 insertions(+), 20 deletions(-) diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h index ccc91fbefb..9340631b94 100644 --- a/servers/slapd/back-meta/back-meta.h +++ b/servers/slapd/back-meta/back-meta.h @@ -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 { diff --git a/servers/slapd/back-meta/conn.c b/servers/slapd/back-meta/conn.c index 1cf911331e..737dc2e057 100644 --- a/servers/slapd/back-meta/conn.c +++ b/servers/slapd/back-meta/conn.c @@ -24,6 +24,7 @@ #include +#include #include #include @@ -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", diff --git a/servers/slapd/back-meta/unbind.c b/servers/slapd/back-meta/unbind.c index f6d62ced67..5211a9dae3 100644 --- a/servers/slapd/back-meta/unbind.c +++ b/servers/slapd/back-meta/unbind.c @@ -24,9 +24,9 @@ #include +#include #include #include -#include #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 );