From a6b3a92cc573101a261906b8d2eb0158b0902c7c Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Thu, 13 Feb 2003 10:43:16 +0000 Subject: [PATCH] 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... --- libraries/libldap/abandon.c | 22 ++++++-- libraries/libldap/ldap-int.h | 5 ++ libraries/libldap/open.c | 5 ++ libraries/libldap/request.c | 39 ++++++++++++-- libraries/libldap/result.c | 99 +++++++++++++++++++++++++----------- libraries/libldap/unbind.c | 27 ++++++++-- 6 files changed, 155 insertions(+), 42 deletions(-) diff --git a/libraries/libldap/abandon.c b/libraries/libldap/abandon.c index aa3f9d5885..7945aa5fdf 100644 --- a/libraries/libldap/abandon.c +++ b/libraries/libldap/abandon.c @@ -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 } } } diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index a769f287af..586b892304 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -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 */ diff --git a/libraries/libldap/open.c b/libraries/libldap/open.c index 149ac4a31a..31db8f49a1 100644 --- a/libraries/libldap/open.c +++ b/libraries/libldap/open.c @@ -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 */ diff --git a/libraries/libldap/request.c b/libraries/libldap/request.c index dedb1ee286..0a61770bc0 100644 --- a/libraries/libldap/request.c +++ b/libraries/libldap/request.c @@ -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 ); } diff --git a/libraries/libldap/result.c b/libraries/libldap/result.c index ac60a337c5..b003e475a5 100644 --- a/libraries/libldap/result.c +++ b/libraries/libldap/result.c @@ -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 ); } diff --git a/libraries/libldap/unbind.c b/libraries/libldap/unbind.c index a34939abc0..2ac13904a6 100644 --- a/libraries/libldap/unbind.c +++ b/libraries/libldap/unbind.c @@ -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 ); } -- 2.39.5