]> git.sur5r.net Git - openldap/commitdiff
fix potential deadlock; first round of refcnt for connections
authorPierangelo Masarati <ando@openldap.org>
Sun, 3 Jul 2005 23:28:35 +0000 (23:28 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sun, 3 Jul 2005 23:28:35 +0000 (23:28 +0000)
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/conn.c
servers/slapd/back-meta/unbind.c

index ccc91fbefbd8b3d1c608219c2171dbf1735a9110..9340631b94dc7979941841282ee1a9938e56df0b 100644 (file)
@@ -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 {
index 1cf911331e7c5cfcf5d063f1662dc617656ca182..737dc2e057bb26e9bacb62309872d186ff89b49e 100644 (file)
@@ -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",
index f6d62ced67583fb398196b135eeeed990a3e9c2e..5211a9dae32b5576ddb6580ad50c1dbf443ca696 100644 (file)
@@ -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 );