ITS#4315 fix bind concurrency issue

This commit is contained in:
Howard Chu 2006-01-09 09:14:53 +00:00
parent be8676f780
commit 2b39a26150
2 changed files with 33 additions and 9 deletions

View 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 */

View 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;