]> git.sur5r.net Git - openldap/commitdiff
ITS#4315 fix bind concurrency issue
authorHoward Chu <hyc@openldap.org>
Mon, 9 Jan 2006 09:14:53 +0000 (09:14 +0000)
committerHoward Chu <hyc@openldap.org>
Mon, 9 Jan 2006 09:14:53 +0000 (09:14 +0000)
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c

index 5e243bc3d68620a027384bf387fcf29396bbf8b9..f994fd116b072005ec3bc6a3418cd6f6812b0f04 100644 (file)
@@ -59,6 +59,7 @@ typedef struct ldapconn_t {
 #define        LDAP_BACK_FCONN_ISBMASK (LDAP_BACK_FCONN_ISBOUND|LDAP_BACK_FCONN_ISANON)
 #define        LDAP_BACK_FCONN_ISPRIV  (0x04)
 #define        LDAP_BACK_FCONN_ISTLS   (0x08)
+#define        LDAP_BACK_FCONN_BINDING (0x10)
 
 #define        LDAP_BACK_CONN_ISBOUND(lc)              LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISBOUND)
 #define        LDAP_BACK_CONN_ISBOUND_SET(lc)          LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISBOUND)
@@ -76,6 +77,9 @@ typedef struct ldapconn_t {
 #define        LDAP_BACK_CONN_ISTLS_SET(lc)            LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISTLS)
 #define        LDAP_BACK_CONN_ISTLS_CLEAR(lc)          LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_ISTLS)
 #define        LDAP_BACK_CONN_ISTLS_CPY(lc, mlc)       LDAP_BACK_CONN_CPY((lc), LDAP_BACK_FCONN_ISTLS, (mlc))
+#define        LDAP_BACK_CONN_BINDING(lc)              LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_BINDING)
+#define        LDAP_BACK_CONN_BINDING_SET(lc)          LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_BINDING)
+#define        LDAP_BACK_CONN_BINDING_CLEAR(lc)        LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_BINDING)
 
        unsigned                lc_refcnt;
        unsigned                lc_flags;
@@ -193,7 +197,9 @@ typedef enum ldap_back_send_t {
        LDAP_BACK_DONTSEND              = 0x00,
        LDAP_BACK_SENDOK                = 0x01,
        LDAP_BACK_SENDERR               = 0x02,
-       LDAP_BACK_SENDRESULT            = (LDAP_BACK_SENDOK|LDAP_BACK_SENDERR)
+       LDAP_BACK_SENDRESULT            = (LDAP_BACK_SENDOK|LDAP_BACK_SENDERR),
+       LDAP_BACK_BINDING               = 0x04,
+       LDAP_BACK_BIND_SERR             = (LDAP_BACK_BINDING|LDAP_BACK_SENDERR)
 } ldap_back_send_t;
 
 /* define to use asynchronous StartTLS */
index cadcaa8b05a9c7038e85dc1ad16dfbf2fa8367e9..8083428730bcf3312746456718a76b0a83ad4fe2 100644 (file)
@@ -56,7 +56,7 @@ ldap_back_bind( Operation *op, SlapReply *rs )
        int rc = 0;
        ber_int_t msgid;
 
-       lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
+       lc = ldap_back_getconn( op, rs, LDAP_BACK_BIND_SERR );
        if ( !lc ) {
                return rs->sr_err;
        }
@@ -489,21 +489,35 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
                }
        }
 
-       /* Searches for a ldapconn in the avl tree */
-       ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
+       /* Explicit Bind requests always get their own conn */
+       if ( sendok & LDAP_BACK_BINDING ) {
+               lc = NULL;
+       } else {
+               /* Searches for a ldapconn in the avl tree */
+retry_lock:
+               ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
 
-       lc = (ldapconn_t *)avl_find( li->li_conninfo.lai_tree, 
-                       (caddr_t)&lc_curr, ldap_back_conn_cmp );
-       if ( lc != NULL ) {
-               refcnt = ++lc->lc_refcnt;
+               lc = (ldapconn_t *)avl_find( li->li_conninfo.lai_tree, 
+                               (caddr_t)&lc_curr, ldap_back_conn_cmp );
+               if ( lc != NULL ) {
+                       refcnt = ++lc->lc_refcnt;
+                       /* Don't reuse connections while they're still binding */
+                       if ( LDAP_BACK_CONN_BINDING( lc )) {
+                               ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
+                               ldap_pvt_thread_yield();
+                               goto retry_lock;
+                       }
+               }
+               ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
        }
-       ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
 
        /* Looks like we didn't get a bind. Open a new session... */
        if ( lc == NULL ) {
                if ( ldap_back_prepare_conn( &lc, op, rs, sendok ) != LDAP_SUCCESS ) {
                        return NULL;
                }
+               if ( sendok & LDAP_BACK_BINDING )
+                       LDAP_BACK_CONN_BINDING_SET( lc );
 
                lc->lc_conn = lc_curr.lc_conn;
                ber_dupbv( &lc->lc_local_ndn, &lc_curr.lc_local_ndn );
@@ -618,6 +632,7 @@ ldap_back_release_conn(
        ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
        assert( lc->lc_refcnt > 0 );
        lc->lc_refcnt--;
+       LDAP_BACK_CONN_BINDING_CLEAR( lc );
        ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
 }
 
@@ -650,6 +665,9 @@ ldap_back_dobind_int(
                return rc;
        }
 
+       while ( lc->lc_refcnt > 1 )
+               ldap_pvt_thread_yield();
+
        /*
         * FIXME: we need to let clients use proxyAuthz
         * otherwise we cannot do symmetric pools of servers;