X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Fresult.c;h=29ea2c8821569eb83f501bac53a3043291845bdf;hb=6d0f6f414f90c67db850751915a6640668d6cd44;hp=6cb3a620a0cae448561c2605f3caf666d1a2a8ca;hpb=e75d729e0f17706d04e5578d2c9c6c4eaa8e11eb;p=openldap diff --git a/libraries/libldap/result.c b/libraries/libldap/result.c index 6cb3a620a0..29ea2c8821 100644 --- a/libraries/libldap/result.c +++ b/libraries/libldap/result.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2007 The OpenLDAP Foundation. + * Copyright 1998-2010 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -71,7 +71,7 @@ static int ldap_mark_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid, int idx )); 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)); @@ -106,7 +106,6 @@ ldap_result( struct timeval *timeout, LDAPMessage **result ) { - LDAPMessage *lm = NULL; int rc; assert( ld != NULL ); @@ -118,19 +117,7 @@ ldap_result( ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex ); #endif -#if 0 - /* this is already done inside wait4msg(), right?... */ - lm = chkResponseList( ld, msgid, all ); -#endif - - 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 ); @@ -289,7 +276,7 @@ wait4msg( } #endif /* LDAP_DEBUG */ - if ( timeout != NULL ) { + if ( timeout != NULL && timeout->tv_sec != -1 ) { tv0 = *timeout; tv = *timeout; tvp = &tv; @@ -322,7 +309,7 @@ wait4msg( } #endif /* LDAP_DEBUG */ - if ( ( *result = chkResponseList( ld, msgid, all ) ) != NULL ) { + if ( ( *result = chkResponseList( ld, msgid, all ) ) != NULL ) { rc = (*result)->lm_msgtype; } else { @@ -335,13 +322,6 @@ wait4msg( 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; } @@ -350,19 +330,21 @@ wait4msg( ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); #endif - if ( !lc_ready ) { + if ( !lc_ready ) { + int err; rc = ldap_int_select( ld, tvp ); -#ifdef LDAP_DEBUG if ( rc == -1 ) { + err = sock_errno(); +#ifdef LDAP_DEBUG Debug( LDAP_DEBUG_TRACE, "ldap_int_select returned -1: errno %d\n", - sock_errno(), 0, 0 ); - } + err, 0, 0 ); #endif + } if ( rc == 0 || ( rc == -1 && ( !LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART) - || sock_errno() != EINTR ) ) ) + || err != EINTR ) ) ) { ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN : LDAP_TIMEOUT); @@ -373,54 +355,63 @@ wait4msg( rc = LDAP_MSG_X_KEEP_LOOKING; /* select interrupted: loop */ } else { - rc = LDAP_MSG_X_KEEP_LOOKING; + lc_ready = 1; + } + } + if ( lc_ready ) { + LDAPConn *lnext; + rc = LDAP_MSG_X_KEEP_LOOKING; #ifdef LDAP_R_COMPILE - ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex ); + 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 ); - } + 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 ); - ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex ); + ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex ); + ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex ); #endif - for ( lc = ld->ld_conns; - rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL; ) + for ( lc = ld->ld_conns; + rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL; + lc = lnext ) + { + if ( lc->lconn_status == LDAP_CONNST_CONNECTED && + ldap_is_read_ready( ld, lc->lconn_sb ) ) { - 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 ); + 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 ); + lnext = 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; } - - /* next conn */ - lc = lc->lconn_next; - } #ifdef LDAP_R_COMPILE - ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); + ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex ); #endif + } else { + lnext = lc->lconn_next; + } } +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); +#endif } } @@ -480,7 +471,7 @@ try_read1msg( LDAP *ld, ber_int_t msgid, int all, - LDAPConn **lcp, + LDAPConn *lc, LDAPMessage **result ) { BerElement *ber; @@ -491,9 +482,8 @@ try_read1msg( ber_len_t len; int foundit = 0; LDAPRequest *lr, *tmplr, dummy_lr = { 0 }; - LDAPConn *lc; BerElement tmpber; - int rc, refer_cnt, hadref, simple_request; + int rc, refer_cnt, hadref, simple_request, err; ber_int_t lderr; #ifdef LDAP_CONNECTIONLESS @@ -502,8 +492,7 @@ try_read1msg( #endif assert( ld != NULL ); - assert( lcp != NULL ); - assert( *lcp != NULL ); + assert( lc != NULL ); #ifdef LDAP_R_COMPILE LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); @@ -512,8 +501,6 @@ try_read1msg( 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 ); @@ -547,25 +534,20 @@ nextresp3: break; case LBER_DEFAULT: + err = sock_errno(); #ifdef LDAP_DEBUG Debug( LDAP_DEBUG_CONNS, "ber_get_next failed.\n", 0, 0, 0 ); #endif #ifdef EWOULDBLOCK - if ( sock_errno() == EWOULDBLOCK ) return LDAP_MSG_X_KEEP_LOOKING; + if ( err == EWOULDBLOCK ) return LDAP_MSG_X_KEEP_LOOKING; #endif #ifdef EAGAIN - if ( sock_errno() == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING; + if ( err == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING; #endif ld->ld_errno = LDAP_SERVER_DOWN; -#ifdef LDAP_R_COMPILE - ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex ); -#endif - ldap_free_connection( ld, lc, 1, 0 ); -#ifdef LDAP_R_COMPILE - ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex ); -#endif - lc = *lcp = NULL; + --lc->lconn_refcnt; + lc->lconn_status = 0; return -1; default: @@ -582,6 +564,11 @@ nextresp3: /* id == 0 iff unsolicited notification message (RFC 4511) */ + /* id < 0 is invalid, just toss it. FIXME: should we disconnect? */ + if ( id < 0 ) { + goto retry_ber; + } + /* if it's been abandoned, toss it */ if ( id > 0 ) { if ( ldap_abandoned( ld, id, &idx ) ) { @@ -602,8 +589,8 @@ nextresp3: } Debug( LDAP_DEBUG_ANY, - "abandoned/discarded ld %p msgid %ld message type %s\n", - (void *)ld, (long)id, ldap_int_msgtype2str( tag ) ); + "abandoned/discarded ld %p msgid %d message type %s\n", + (void *)ld, id, ldap_int_msgtype2str( tag ) ); retry_ber: ber_free( ber, 1 ); @@ -629,8 +616,8 @@ retry_ber: } Debug( LDAP_DEBUG_ANY, - "no request for response on ld %p msgid %ld message type %s (tossing)\n", - (void *)ld, (long)id, msg ); + "no request for response on ld %p msgid %d message type %s (tossing)\n", + (void *)ld, id, msg ); goto retry_ber; } @@ -640,6 +627,7 @@ retry_ber: ber_scanf(ber, "x{"); } nextresp2: + ; #endif } @@ -652,8 +640,8 @@ nextresp2: } Debug( LDAP_DEBUG_TRACE, - "read1msg: ld %p msgid %ld message type %s\n", - (void *)ld, (long)lr->lr_msgid, ldap_int_msgtype2str( tag ) ); + "read1msg: ld %p msgid %d message type %s\n", + (void *)ld, id, ldap_int_msgtype2str( tag ) ); if ( id == 0 ) { /* unsolicited notification message (RFC 4511) */ @@ -857,6 +845,10 @@ nextresp2: return( -1 ); /* fatal error */ } lr->lr_res_errno = LDAP_SUCCESS; /* sucessfully chased referral */ + if ( lr->lr_res_matched ) { + LDAP_FREE( lr->lr_res_matched ); + lr->lr_res_matched = NULL; + } } else { if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) { @@ -900,8 +892,8 @@ nextresp2: { id = lr->lr_msgid; tag = lr->lr_res_msgtype; - Debug( LDAP_DEBUG_TRACE, "request done: ld %p msgid %ld\n", - (void *)ld, (long) id, 0 ); + Debug( LDAP_DEBUG_TRACE, "request done: ld %p msgid %d\n", + (void *)ld, id, 0 ); Debug( LDAP_DEBUG_TRACE, "res_errno: %d, res_error: <%s>, " "res_matched: <%s>\n", @@ -929,14 +921,8 @@ nextresp2: * shouldn't necessarily end the connection */ if ( lc != NULL && id != 0 ) { -#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; } } } @@ -1002,14 +988,7 @@ nextresp2: /* get rid of the connection... */ 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; } /* need to return -1, because otherwise @@ -1118,7 +1097,8 @@ nextresp2: if ( msgid == LDAP_RES_ANY || id == msgid ) { if ( all == LDAP_MSG_ONE || ( newmsg->lm_msgtype != LDAP_RES_SEARCH_RESULT - && newmsg->lm_msgtype != LDAP_RES_SEARCH_ENTRY + && newmsg->lm_msgtype != LDAP_RES_SEARCH_ENTRY + && newmsg->lm_msgtype != LDAP_RES_INTERMEDIATE && newmsg->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) ) { *result = newmsg; @@ -1156,8 +1136,8 @@ nextresp2: goto exit; } - Debug( LDAP_DEBUG_TRACE, "adding response ld %p msgid %ld type %ld:\n", - (void *)ld, (long) newmsg->lm_msgid, (long) newmsg->lm_msgtype ); + Debug( LDAP_DEBUG_TRACE, "adding response ld %p msgid %d type %ld:\n", + (void *)ld, newmsg->lm_msgid, (long) newmsg->lm_msgtype ); /* part of a search response - add to end of list of entries */ l->lm_chain_tail->lm_chain = newmsg; @@ -1407,7 +1387,6 @@ ldap_abandoned( LDAP *ld, ber_int_t msgid, int *idxp ) assert( idxp != NULL ); assert( msgid >= 0 ); - assert( ld->ld_nabandoned >= 0 ); return ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, idxp ); } @@ -1426,7 +1405,7 @@ ldap_mark_abandoned( LDAP *ld, ber_int_t msgid, int idx ) /* NOTE: those assertions are repeated in ldap_int_bisect_delete() */ assert( idx >= 0 ); - assert( idx < ld->ld_nabandoned ); + assert( (unsigned) idx < ld->ld_nabandoned ); assert( ld->ld_abandoned[ idx ] == msgid ); return ldap_int_bisect_delete( &ld->ld_abandoned, &ld->ld_nabandoned,