Commit a6b3a92c authored by Howard Chu's avatar Howard Chu
Browse files

Added ld_req_mutex and ld_res_mutex to protect ld_requests and ld_responses

queues for multithreaded access to LDAP*'s. Also used to protect writes and
reads of ld_sb, respectively. Appears to work...
parent 568829d8
......@@ -32,7 +32,8 @@ static int do_abandon LDAP_P((
ber_int_t origid,
ber_int_t msgid,
LDAPControl **sctrls,
LDAPControl **cctrls));
LDAPControl **cctrls,
int lock));
/*
* ldap_abandon_ext - perform an ldap extended abandon operation.
......@@ -67,7 +68,7 @@ ldap_abandon_ext(
rc = ldap_int_client_controls( ld, cctrls );
if( rc != LDAP_SUCCESS ) return rc;
return do_abandon( ld, msgid, msgid, sctrls, cctrls );
return do_abandon( ld, msgid, msgid, sctrls, cctrls, 1 );
}
......@@ -101,7 +102,8 @@ do_abandon(
ber_int_t origid,
ber_int_t msgid,
LDAPControl **sctrls,
LDAPControl **cctrls)
LDAPControl **cctrls,
int lock)
{
BerElement *ber;
int i, err, sendabandon;
......@@ -118,6 +120,9 @@ do_abandon(
sendabandon = 1;
#ifdef LDAP_R_COMPILE
if ( lock ) ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
/* find the request that we are abandoning */
for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
if ( lr->lr_msgid == msgid ) { /* this message */
......@@ -125,9 +130,12 @@ do_abandon(
}
if ( lr->lr_origid == msgid ) {/* child: abandon it */
(void) do_abandon( ld,
msgid, lr->lr_msgid, sctrls, cctrls );
msgid, lr->lr_msgid, sctrls, cctrls, 0 );
}
}
#ifdef LDAP_R_COMPILE
if ( lock ) ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
if ( lr != NULL ) {
if ( origid == msgid && lr->lr_parent != NULL ) {
......@@ -213,12 +221,18 @@ do_abandon(
sb = ld->ld_sb;
}
#ifdef LDAP_R_COMPILE
if ( lock ) ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
if ( ber_flush( sb, ber, 1 ) != 0 ) {
ld->ld_errno = LDAP_SERVER_DOWN;
err = -1;
} else {
err = 0;
}
#ifdef LDAP_R_COMPILE
if ( lock ) ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
}
}
}
......
......@@ -302,6 +302,11 @@ struct ldap {
LDAPRequest *ld_requests; /* list of outstanding requests */
LDAPMessage *ld_responses; /* list of outstanding responses */
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_t ld_req_mutex;
ldap_pvt_thread_mutex_t ld_res_mutex;
#endif
ber_int_t *ld_abandoned; /* array of abandoned requests */
LDAPCache *ld_cache; /* non-null if cache is initialized */
......
......@@ -160,6 +160,10 @@ ldap_create( LDAP **ldp )
return LDAP_NO_MEMORY;
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_init( &ld->ld_req_mutex );
ldap_pvt_thread_mutex_init( &ld->ld_res_mutex );
#endif
*ldp = ld;
return LDAP_SUCCESS;
}
......@@ -419,6 +423,7 @@ int ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
lr->lr_msgid = 0;
lr->lr_status = LDAP_REQST_INPROGRESS;
lr->lr_res_errno = LDAP_SUCCESS;
/* no mutex lock needed, we just created this ld here */
(*ldp)->ld_requests = lr;
/* Attach the passed socket as the *LDAP's connection */
......
......@@ -186,7 +186,7 @@ ldap_send_server_request(
LDAPreqinfo *bind )
{
LDAPRequest *lr;
int incparent;
int incparent, rc;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ENTRY, "ldap_send_server_request\n", 0, 0, 0 );
......@@ -232,11 +232,19 @@ ldap_send_server_request(
* LDAP_BUSY and let the caller retry later. We only allow a single
* request to be in WRITING state.
*/
rc = 0;
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
if ( ld->ld_requests &&
ld->ld_requests->lr_status == LDAP_REQST_WRITING &&
ldap_int_flush_request( ld, ld->ld_requests ) < 0 ) {
return -1;
rc = -1;
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
if ( rc ) return rc;
if (( lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ))) ==
NULL ) {
......@@ -268,17 +276,23 @@ ldap_send_server_request(
lr->lr_origid = lr->lr_msgid;
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
if (( lr->lr_next = ld->ld_requests ) != NULL ) {
lr->lr_next->lr_prev = lr;
}
ld->ld_requests = lr;
lr->lr_prev = NULL;
ld->ld_errno = LDAP_SUCCESS;
if ( ldap_int_flush_request( ld, lr ) == -1 ) {
return -1;
msgid = -1;
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
ld->ld_errno = LDAP_SUCCESS;
return( msgid );
}
......@@ -572,6 +586,9 @@ ldap_dump_requests_and_responses( LDAP *ld )
LDAPRequest *lr;
LDAPMessage *lm, *l;
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
fprintf( stderr, "** Outstanding Requests:\n" );
if (( lr = ld->ld_requests ) == NULL ) {
fprintf( stderr, " Empty\n" );
......@@ -587,7 +604,10 @@ ldap_dump_requests_and_responses( LDAP *ld )
fprintf( stderr, " outstanding referrals %d, parent count %d\n",
lr->lr_outrefcnt, lr->lr_parentcnt );
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
#endif
fprintf( stderr, "** Response Queue:\n" );
if (( lm = ld->ld_responses ) == NULL ) {
fprintf( stderr, " Empty\n" );
......@@ -605,6 +625,9 @@ ldap_dump_requests_and_responses( LDAP *ld )
}
}
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
#endif
}
#endif /* LDAP_DEBUG */
......@@ -1241,6 +1264,9 @@ ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
{
LDAPRequest *lr;
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
if( lr->lr_status == LDAP_REQST_COMPLETED ) {
continue; /* Skip completed requests */
......@@ -1249,6 +1275,9 @@ ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
break;
}
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
return( lr );
}
......
......@@ -141,6 +141,9 @@ chkResponseList(
msgid, all, 0 );
#endif
lastlm = NULL;
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
#endif
for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) {
nextlm = lm->lm_next;
......@@ -207,6 +210,9 @@ chkResponseList(
}
lm->lm_next = NULL;
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
#endif
#ifdef LDAP_DEBUG
if( lm == NULL) {
......@@ -308,7 +314,13 @@ wait4msg(
}
if ( lc == NULL ) {
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
#endif
rc = ldap_int_select( ld, tvp );
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
#endif
#ifdef LDAP_DEBUG
......@@ -338,12 +350,18 @@ wait4msg(
rc = -2; /* select interrupted: loop */
} else {
rc = -2;
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
if ( ld->ld_requests &&
ld->ld_requests->lr_status == LDAP_REQST_WRITING &&
ldap_is_write_ready( ld,
ld->ld_requests->lr_conn->lconn_sb ) ) {
ldap_int_flush_request( ld, ld->ld_requests );
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
for ( lc = ld->ld_conns; rc == -2 && lc != NULL;
lc = nextlc ) {
nextlc = lc->lconn_next;
......@@ -417,18 +435,23 @@ try_read1msg(
#endif
retry:
if ( lc->lconn_ber == NULL ) {
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
#endif
if ( lc->lconn_ber == NULL ) {
lc->lconn_ber = ldap_alloc_ber_with_options(ld);
if( lc->lconn_ber == NULL ) {
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
#endif
return -1;
}
}
}
ber = lc->lconn_ber;
assert( LBER_VALID (ber) );
retry2:
/* get the next message */
errno = 0;
#ifdef LDAP_CONNECTIONLESS
......@@ -437,8 +460,18 @@ retry2:
ber_int_sb_read(sb, &from, sizeof(struct sockaddr));
}
#endif
if ( (tag = ber_get_next( sb, &len, ber ))
!= LDAP_TAG_MESSAGE ) {
tag = ber_get_next( sb, &len, ber );
if ( tag == LDAP_TAG_MESSAGE ) {
/*
* We read a complete message.
* The connection should no longer need this ber.
*/
lc->lconn_ber = NULL;
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
#endif
if ( tag != LDAP_TAG_MESSAGE ) {
if ( tag == LBER_DEFAULT) {
#ifdef LDAP_DEBUG
#ifdef NEW_LOGGING
......@@ -462,12 +495,6 @@ retry2:
return -1;
}
/*
* We read a complete message.
* The connection should no longer need this ber.
*/
lc->lconn_ber = NULL;
/* message id */
if ( ber_get_int( ber, &id ) == LBER_ERROR ) {
ber_free( ber, 1 );
......@@ -483,12 +510,10 @@ retry2:
Debug( LDAP_DEBUG_ANY, "abandoned\n", 0, 0, 0);
#endif
retry_ber:
ber_free( ber, 1 );
if ( ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL ) ) {
ber_free_buf( ber );
ber_init2( ber, NULL, ld->ld_lberoptions );
goto retry2;
goto retry;
}
ber_free( ber, 1 );
return( -2 ); /* continue looking */
}
......@@ -832,6 +857,9 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
* search response.
*/
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
#endif
prev = NULL;
for ( l = ld->ld_responses; l != NULL; l = l->lm_next ) {
if ( l->lm_msgid == new->lm_msgid )
......@@ -843,8 +871,7 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
if ( l == NULL ) {
if ( foundit ) {
*result = new;
ld->ld_errno = LDAP_SUCCESS;
return( tag );
goto leave;
}
new->lm_next = ld->ld_responses;
......@@ -877,11 +904,16 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
else
prev->lm_next = l->lm_next;
*result = l;
ld->ld_errno = LDAP_SUCCESS;
return( tag );
}
leave:
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
#endif
if ( foundit ) {
ld->ld_errno = LDAP_SUCCESS;
return( tag );
}
if ( ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL ) ) {
goto retry;
}
......@@ -1056,6 +1088,7 @@ int
ldap_msgdelete( LDAP *ld, int msgid )
{
LDAPMessage *lm, *prev;
int rc = 0;
assert( ld != NULL );
......@@ -1066,24 +1099,30 @@ ldap_msgdelete( LDAP *ld, int msgid )
#endif
prev = NULL;
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
#endif
for ( lm = ld->ld_responses; lm != NULL; lm = lm->lm_next ) {
if ( lm->lm_msgid == msgid )
break;
prev = lm;
}
if ( lm == NULL )
return( -1 );
if ( prev == NULL )
ld->ld_responses = lm->lm_next;
else
prev->lm_next = lm->lm_next;
if ( ldap_msgfree( lm ) == LDAP_RES_SEARCH_ENTRY )
return( -1 );
if ( lm == NULL ) {
rc = -1;
} else {
if ( prev == NULL )
ld->ld_responses = lm->lm_next;
else
prev->lm_next = lm->lm_next;
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
#endif
if ( lm && ldap_msgfree( lm ) == LDAP_RES_SEARCH_ENTRY )
rc = -1;
return( 0 );
return( rc );
}
......
......@@ -79,20 +79,31 @@ ldap_ld_free(
int err = LDAP_SUCCESS;
/* free LDAP structure and outstanding requests/responses */
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
while ( ld->ld_requests != NULL ) {
ldap_free_request( ld, ld->ld_requests );
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
/* free and unbind from all open connections */
while ( ld->ld_conns != NULL ) {
ldap_free_connection( ld, ld->ld_conns, 1, close );
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
#endif
for ( lm = ld->ld_responses; lm != NULL; lm = next ) {
next = lm->lm_next;
ldap_msgfree( lm );
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
#endif
if ( ld->ld_error != NULL ) {
LDAP_FREE( ld->ld_error );
......@@ -158,6 +169,10 @@ ldap_ld_free(
ber_sockbuf_free( ld->ld_sb );
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_destroy( &ld->ld_req_mutex );
ldap_pvt_thread_mutex_destroy( &ld->ld_res_mutex );
#endif
LDAP_FREE( (char *) ld );
return( err );
......@@ -214,12 +229,18 @@ ldap_send_unbind(
return( ld->ld_errno );
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
ld->ld_errno = LDAP_SUCCESS;
/* send the message */
if ( ber_flush( sb, ber, 1 ) == -1 ) {
ld->ld_errno = LDAP_SERVER_DOWN;
ber_free( ber, 1 );
return( ld->ld_errno );
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
return( LDAP_SUCCESS );
return( ld->ld_errno );
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment