diff -up openldap-2.3.43/libraries/libldap/os-ip.c.orig openldap-2.3.43/libraries/libldap/os-ip.c --- openldap-2.3.43/libraries/libldap/os-ip.c.orig 2008-05-19 19:28:54.000000000 -0400 +++ openldap-2.3.43/libraries/libldap/os-ip.c 2009-07-29 17:01:32.000000000 -0400 @@ -738,6 +738,9 @@ ldap_mark_select_read( LDAP *ld, Sockbuf sip = (struct selectinfo *)ld->ld_selectinfo; + if (ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL )) + return; + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); #ifdef HAVE_POLL diff -up openldap-2.3.43/libraries/libldap/result.c.orig openldap-2.3.43/libraries/libldap/result.c --- openldap-2.3.43/libraries/libldap/result.c.orig 2009-07-29 17:00:42.000000000 -0400 +++ openldap-2.3.43/libraries/libldap/result.c 2009-07-29 18:10:35.000000000 -0400 @@ -73,7 +73,7 @@ static int ldap_mark_abandoned LDAP_P(( static int wait4msg LDAP_P(( LDAP *ld, ber_int_t msgid, int all, struct timeval *timeout, LDAPMessage **result )); static ber_tag_t try_read1msg LDAP_P(( LDAP *ld, ber_int_t msgid, - int all, LDAPConn **lc, LDAPMessage **result )); + int all, LDAPConn *lc, LDAPMessage **result )); static ber_tag_t build_result_ber LDAP_P(( LDAP *ld, BerElement **bp, LDAPRequest *lr )); static void merge_error_info LDAP_P(( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr )); static LDAPMessage * chkResponseList LDAP_P(( LDAP *ld, int msgid, int all)); @@ -118,15 +118,9 @@ ldap_result( #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex ); #endif - lm = chkResponseList(ld, msgid, all); - if ( lm == NULL ) { - rc = wait4msg( ld, msgid, all, timeout, result ); - } else { - *result = lm; - ld->ld_errno = LDAP_SUCCESS; - rc = lm->lm_msgtype; - } + rc = wait4msg( ld, msgid, all, timeout, result ); + #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex ); #endif @@ -233,7 +227,7 @@ wait4msg( *tvp; time_t start_time = 0; time_t tmp_time; - LDAPConn *lc; + LDAPConn *lc, *nextlc; assert( ld != NULL ); assert( result != NULL ); @@ -280,13 +274,6 @@ wait4msg( for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { if ( ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) { -#ifdef LDAP_R_COMPILE - ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); -#endif - rc = try_read1msg( ld, msgid, all, &lc, result ); -#ifdef LDAP_R_COMPILE - ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex ); -#endif lc_ready = 1; break; } @@ -319,7 +306,11 @@ wait4msg( if ( rc == -1 ) { rc = LDAP_MSG_X_KEEP_LOOKING; /* select interrupted: loop */ } else { - rc = LDAP_MSG_X_KEEP_LOOKING; + lc_ready = 1; + } + } + if ( lc_ready ) { + rc = LDAP_MSG_X_KEEP_LOOKING; #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex ); #endif @@ -335,38 +326,43 @@ wait4msg( ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex ); #endif for ( lc = ld->ld_conns; - rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL; ) + rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL; + lc = nextlc ) { if ( lc->lconn_status == LDAP_CONNST_CONNECTED && ldap_is_read_ready( ld, lc->lconn_sb )) { + /* Don't let it get freed out from under us */ + ++lc->lconn_refcnt; #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); #endif - rc = try_read1msg( ld, msgid, all, &lc, result ); + rc = try_read1msg( ld, msgid, all, lc, result ); + nextlc = lc->lconn_next; + + /* Only take locks if we're really freeing */ + if ( lc->lconn_refcnt <= 1 ) { #ifdef LDAP_R_COMPILE - ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex ); + ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex ); #endif - if ( lc == NULL ) { - /* if lc gets free()'d, - * there's no guarantee - * lc->lconn_next is still - * sane; better restart - * (ITS#4405) */ - lc = ld->ld_conns; - - /* don't get to next conn! */ - break; + ldap_free_connection( ld, lc, 0, 1 ); +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex ); +#endif + } else { + --lc->lconn_refcnt; } +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex ); +#endif + } else { + /* next conn */ + nextlc = lc->lconn_next; } - - /* next conn */ - lc = lc->lconn_next; } #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); #endif - } } } @@ -380,7 +376,6 @@ wait4msg( if ( tv0.tv_sec <= delta_time ) { rc = 0; /* timed out */ ld->ld_errno = LDAP_TIMEOUT; - break; } tv0.tv_sec -= delta_time; tv.tv_sec = tv0.tv_sec; @@ -400,7 +395,7 @@ try_read1msg( LDAP *ld, ber_int_t msgid, int all, - LDAPConn **lcp, + LDAPConn *lc, LDAPMessage **result ) { BerElement *ber; @@ -410,7 +405,6 @@ try_read1msg( ber_len_t len; int foundit = 0; LDAPRequest *lr, *tmplr; - LDAPConn *lc; BerElement tmpber; int rc, refer_cnt, hadref, simple_request, err; ber_int_t lderr; @@ -431,14 +425,11 @@ try_read1msg( } v3ref; assert( ld != NULL ); - assert( lcp != NULL ); - assert( *lcp != NULL ); + assert( lc != NULL ); Debug( LDAP_DEBUG_TRACE, "read1msg: ld %p msgid %d all %d\n", (void *)ld, msgid, all ); - lc = *lcp; - retry: if ( lc->lconn_ber == NULL ) { lc->lconn_ber = ldap_alloc_ber_with_options(ld); @@ -839,14 +830,8 @@ lr->lr_res_matched ? lr->lr_res_matched } if ( lc != NULL ) { -#ifdef LDAP_R_COMPILE - ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex ); -#endif - ldap_free_connection( ld, lc, 0, 1 ); -#ifdef LDAP_R_COMPILE - ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex ); -#endif - lc = *lcp = NULL; + --lc->lconn_refcnt; + lc = NULL; } } }