/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2007 The OpenLDAP Foundation.
+ * Copyright 1998-2012 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include "ldap_log.h"
#include "lutil.h"
-static int ldap_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid, int *idx ));
-static int ldap_mark_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid, int idx ));
+static int ldap_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid ));
+static int ldap_mark_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid ));
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));
struct timeval *timeout,
LDAPMessage **result )
{
- LDAPMessage *lm = NULL;
int rc;
assert( ld != NULL );
Debug( LDAP_DEBUG_TRACE, "ldap_result ld %p msgid %d\n", (void *)ld, msgid, 0 );
-#ifdef LDAP_R_COMPILE
- 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;
- }
-
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
-#endif
+ LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
+ rc = wait4msg( ld, msgid, all, timeout, result );
+ LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
return rc;
}
+/* protected by res_mutex */
static LDAPMessage *
chkResponseList(
LDAP *ld,
* wait until it arrives or timeout occurs.
*/
-#ifdef LDAP_R_COMPILE
- LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
-#endif
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
Debug( LDAP_DEBUG_TRACE,
"ldap_chkResponseList ld %p msgid %d all %d\n",
lastlm = &ld->ld_responses;
for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) {
- int idx;
-
nextlm = lm->lm_next;
++cnt;
- if ( ldap_abandoned( ld, lm->lm_msgid, &idx ) ) {
+ if ( ldap_abandoned( ld, lm->lm_msgid ) ) {
Debug( LDAP_DEBUG_ANY,
"response list msg abandoned, "
"msgid %d message type %s\n",
default:
/* there's no need to keep the id
* in the abandoned list any longer */
- ldap_mark_abandoned( ld, lm->lm_msgid, idx );
+ ldap_mark_abandoned( ld, lm->lm_msgid );
break;
}
"ldap_chkResponseList returns ld %p NULL\n", (void *)ld, 0, 0);
} else {
Debug( LDAP_DEBUG_TRACE,
- "ldap_chkResponseList returns ld %p msgid %d, type 0x%02lu\n",
+ "ldap_chkResponseList returns ld %p msgid %d, type 0x%02lx\n",
(void *)ld, lm->lm_msgid, (unsigned long)lm->lm_msgtype );
}
#endif
return lm;
}
+/* protected by res_mutex */
static int
wait4msg(
LDAP *ld,
int rc;
struct timeval tv = { 0 },
tv0 = { 0 },
- *tvp;
- time_t start_time = 0;
- time_t tmp_time;
+ start_time_tv = { 0 },
+ *tvp = NULL;
LDAPConn *lc;
assert( ld != NULL );
assert( result != NULL );
-#ifdef LDAP_R_COMPILE
- LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
-#endif
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
+
+ if ( timeout == NULL && ld->ld_options.ldo_tm_api.tv_sec >= 0 ) {
+ tv = ld->ld_options.ldo_tm_api;
+ timeout = &tv;
+ }
#ifdef LDAP_DEBUG
if ( timeout == NULL ) {
}
#endif /* LDAP_DEBUG */
- if ( timeout == NULL ) {
- tvp = NULL;
- } else {
+ if ( timeout != NULL && timeout->tv_sec != -1 ) {
tv0 = *timeout;
tv = *timeout;
tvp = &tv;
- start_time = time( NULL );
+#ifdef HAVE_GETTIMEOFDAY
+ gettimeofday( &start_time_tv, NULL );
+#else /* ! HAVE_GETTIMEOFDAY */
+ time( &start_time_tv.tv_sec );
+ start_time_tv.tv_usec = 0;
+#endif /* ! HAVE_GETTIMEOFDAY */
}
rc = LDAP_MSG_X_KEEP_LOOKING;
if ( ldap_debug & LDAP_DEBUG_TRACE ) {
Debug( LDAP_DEBUG_TRACE, "wait4msg continue ld %p msgid %d all %d\n",
(void *)ld, msgid, all );
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex );
-#endif
ldap_dump_connection( ld, ld->ld_conns, 1 );
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
- ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
-#endif
+ LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
ldap_dump_requests_and_responses( ld );
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
-#endif
+ LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
}
#endif /* LDAP_DEBUG */
- if ( ( *result = chkResponseList( ld, msgid, all ) ) != NULL ) {
+ if ( ( *result = chkResponseList( ld, msgid, all ) ) != NULL ) {
rc = (*result)->lm_msgtype;
} else {
int lc_ready = 0;
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex );
-#endif
+ LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
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;
}
}
-#ifdef LDAP_R_COMPILE
- 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);
+ LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
return( rc );
}
rc = LDAP_MSG_X_KEEP_LOOKING; /* select interrupted: loop */
} else {
- rc = LDAP_MSG_X_KEEP_LOOKING;
-#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 );
- ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex );
-#endif
- for ( lc = ld->ld_conns;
- rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL; )
+ lc_ready = 1;
+ }
+ }
+ if ( lc_ready ) {
+ LDAPConn *lnext;
+ int serviced = 0;
+ rc = LDAP_MSG_X_KEEP_LOOKING;
+ LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
+ if ( ld->ld_requests &&
+ ld->ld_requests->lr_status == LDAP_REQST_WRITING &&
+ ldap_is_write_ready( ld,
+ ld->ld_requests->lr_conn->lconn_sb ) )
+ {
+ serviced = 1;
+ ldap_int_flush_request( ld, ld->ld_requests );
+ }
+ 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 ) )
- {
-#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
- 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;
- }
+ serviced = 1;
+ /* Don't let it get freed out from under us */
+ ++lc->lconn_refcnt;
+ 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 ) {
+ ldap_free_connection( ld, lc, 0, 1 );
+ } else {
+ --lc->lconn_refcnt;
}
-
- /* next conn */
- lc = lc->lconn_next;
+ } else {
+ lnext = lc->lconn_next;
}
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
-#endif
}
+ LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
+ /* Quit looping if no one handled any events */
+ if (!serviced)
+ rc = -1;
}
+ LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
}
if ( rc == LDAP_MSG_X_KEEP_LOOKING && tvp != NULL ) {
- tmp_time = time( NULL );
- tv0.tv_sec -= ( tmp_time - start_time );
- if ( tv0.tv_sec <= 0 ) {
- rc = 0; /* timed out */
+ struct timeval curr_time_tv = { 0 },
+ delta_time_tv = { 0 };
+
+#ifdef HAVE_GETTIMEOFDAY
+ gettimeofday( &curr_time_tv, NULL );
+#else /* ! HAVE_GETTIMEOFDAY */
+ time( &curr_time_tv.tv_sec );
+ curr_time_tv.tv_usec = 0;
+#endif /* ! HAVE_GETTIMEOFDAY */
+
+ /* delta_time = tmp_time - start_time */
+ delta_time_tv.tv_sec = curr_time_tv.tv_sec - start_time_tv.tv_sec;
+ delta_time_tv.tv_usec = curr_time_tv.tv_usec - start_time_tv.tv_usec;
+ if ( delta_time_tv.tv_usec < 0 ) {
+ delta_time_tv.tv_sec--;
+ delta_time_tv.tv_usec += 1000000;
+ }
+
+ /* tv0 < delta_time ? */
+ if ( ( tv0.tv_sec < delta_time_tv.tv_sec ) ||
+ ( ( tv0.tv_sec == delta_time_tv.tv_sec ) && ( tv0.tv_usec < delta_time_tv.tv_usec ) ) )
+ {
+ rc = 0; /* timed out */
ld->ld_errno = LDAP_TIMEOUT;
break;
}
+
+ /* tv0 -= delta_time */
+ tv0.tv_sec -= delta_time_tv.tv_sec;
+ tv0.tv_usec -= delta_time_tv.tv_usec;
+ if ( tv0.tv_usec < 0 ) {
+ tv0.tv_sec--;
+ tv0.tv_usec += 1000000;
+ }
+
tv.tv_sec = tv0.tv_sec;
+ tv.tv_usec = tv0.tv_usec;
+
+ Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p %ld s %ld us to go\n",
+ (void *)ld, (long) tv.tv_sec, (long) tv.tv_usec );
- Debug( LDAP_DEBUG_TRACE, "wait4msg ld %p %ld secs to go\n",
- (void *)ld, (long) tv.tv_sec, 0 );
- start_time = tmp_time;
+ start_time_tv.tv_sec = curr_time_tv.tv_sec;
+ start_time_tv.tv_usec = curr_time_tv.tv_usec;
}
}
}
+/* protected by res_mutex, conn_mutex and req_mutex */
static ber_tag_t
try_read1msg(
LDAP *ld,
ber_int_t msgid,
int all,
- LDAPConn **lcp,
+ LDAPConn *lc,
LDAPMessage **result )
{
BerElement *ber;
LDAPMessage *newmsg, *l, *prev;
ber_int_t id;
- int idx;
ber_tag_t tag;
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
#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 );
-#endif
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
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 );
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;
-#endif
-#ifdef EAGAIN
- if ( sock_errno() == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING;
-#endif
+ if ( err == EWOULDBLOCK ) return LDAP_MSG_X_KEEP_LOOKING;
+ if ( err == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING;
ld->ld_errno = LDAP_SERVER_DOWN;
+ --lc->lconn_refcnt;
+ lc->lconn_status = 0;
return -1;
default:
/* 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 ) ) {
+ if ( ldap_abandoned( ld, id ) ) {
/* the message type */
tag = ber_peek_tag( ber, &len );
switch ( tag ) {
default:
/* there's no need to keep the id
* in the abandoned list any longer */
- ldap_mark_abandoned( ld, id, idx );
+ ldap_mark_abandoned( ld, id );
break;
}
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 );
}
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;
}
ber_scanf(ber, "x{");
}
nextresp2:
+ ;
#endif
}
}
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) */
}
/* Do we need to check for referrals? */
- if ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) ||
- lr->lr_parent != NULL )
+ if ( tag != LDAP_RES_BIND &&
+ ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) ||
+ lr->lr_parent != NULL ))
{
char **refs = NULL;
ber_len_t len;
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 ) {
Debug( LDAP_DEBUG_TRACE,
"read1msg: mark request completed, ld %p msgid %d\n",
(void *)ld, lr->lr_msgid, 0);
+ tmplr = lr;
while ( lr->lr_parent != NULL ) {
merge_error_info( ld, lr->lr_parent, lr );
break; /* not completely done yet */
}
}
+ /* ITS#6744: Original lr was refcounted when we retrieved it,
+ * must release it now that we're working with the parent
+ */
+ if ( tmplr->lr_parent ) {
+ ldap_return_request( ld, tmplr, 0 );
+ }
/* Check if all requests are finished, lr is now parent */
tmplr = lr;
{
id = lr->lr_msgid;
tag = lr->lr_res_msgtype;
- Debug( LDAP_DEBUG_ANY, "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",
lr = NULL;
}
- 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;
+ /*
+ * RFC 4511 unsolicited (id == 0) responses
+ * shouldn't necessarily end the connection
+ */
+ if ( lc != NULL && id != 0 ) {
+ --lc->lconn_refcnt;
+ lc = NULL;
}
}
}
}
/* try to handle unsolicited responses as appropriate */
- if ( id == 0 && msgid != LDAP_RES_UNSOLICITED ) {
+ if ( id == 0 && msgid > LDAP_RES_UNSOLICITED ) {
int is_nod = 0;
- tag = ber_peek_tag( ber, &len );
+ tag = ber_peek_tag( &tmpber, &len );
/* we have a res oid */
if ( tag == LDAP_TAG_EXOP_RES_OID ) {
- char *resoid = NULL;
+ static struct berval bv_nod = BER_BVC( LDAP_NOTICE_OF_DISCONNECTION );
+ struct berval resoid = BER_BVNULL;
- if ( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) {
+ if ( ber_scanf( &tmpber, "m", &resoid ) == LBER_ERROR ) {
ld->ld_errno = LDAP_DECODING_ERROR;
ber_free( ber, 1 );
return -1;
}
- assert( resoid[ 0 ] != '\0' );
+ assert( !BER_BVISEMPTY( &resoid ) );
- is_nod = strcmp( resoid, LDAP_NOTICE_OF_DISCONNECTION ) == 0;
- LDAP_FREE( resoid );
+ is_nod = ber_bvcmp( &resoid, &bv_nod ) == 0;
- tag = ber_peek_tag( ber, &len );
+ tag = ber_peek_tag( &tmpber, &len );
}
- /* we have a res value */
+#if 0 /* don't need right now */
+ /* we have res data */
if ( tag == LDAP_TAG_EXOP_RES_VALUE ) {
- /* don't need right now */
+ struct berval resdata;
+
+ if ( ber_scanf( &tmpber, "m", &resdata ) == LBER_ERROR ) {
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ ber_free( ber, 0 );
+ return ld->ld_errno;
+ }
+
+ /* use it... */
}
+#endif
/* handle RFC 4511 "Notice of Disconnection" locally */
/* 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
- *lcp = NULL;
+ --lc->lconn_refcnt;
}
- return LDAP_RES_EXTENDED;
+ /* need to return -1, because otherwise
+ * a valid result is expected */
+ ld->ld_errno = lderr;
+ return -1;
}
}
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;
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;
Debug( LDAP_DEBUG_TRACE, "ldap_msgdelete ld=%p msgid=%d\n",
(void *)ld, msgid, 0 );
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
-#endif
+ LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
prev = NULL;
for ( lm = ld->ld_responses; lm != NULL; lm = lm->lm_next ) {
if ( lm->lm_msgid == msgid ) {
prev->lm_next = lm->lm_next;
}
}
-#ifdef LDAP_R_COMPILE
- ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
-#endif
+ LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
if ( lm ) {
switch ( ldap_msgfree( lm ) ) {
case LDAP_RES_SEARCH_ENTRY:
*
* return the location of the message id in the array of abandoned
* message ids, or -1
- *
- * expects ld_res_mutex to be locked
*/
static int
-ldap_abandoned( LDAP *ld, ber_int_t msgid, int *idxp )
+ldap_abandoned( LDAP *ld, ber_int_t msgid )
{
-#ifdef LDAP_R_COMPILE
- LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
-#endif
-
- assert( idxp != NULL );
+ int ret, idx;
assert( msgid >= 0 );
- assert( ld->ld_nabandoned >= 0 );
- return ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, idxp );
+ LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex );
+ ret = ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &idx );
+ LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
+ return ret;
}
/*
* ldap_mark_abandoned
- *
- * expects ld_res_mutex to be locked
*/
static int
-ldap_mark_abandoned( LDAP *ld, ber_int_t msgid, int idx )
+ldap_mark_abandoned( LDAP *ld, ber_int_t msgid )
{
-#ifdef LDAP_R_COMPILE
- LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
-#endif
-
- /* NOTE: those assertions are repeated in ldap_int_bisect_delete() */
- assert( idx >= 0 );
- assert( idx < ld->ld_nabandoned );
- assert( ld->ld_abandoned[ idx ] == msgid );
+ int ret, idx;
- return ldap_int_bisect_delete( &ld->ld_abandoned, &ld->ld_nabandoned,
+ assert( msgid >= 0 );
+ LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex );
+ ret = ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &idx );
+ if (ret <= 0) { /* error or already deleted by another thread */
+ LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
+ return ret;
+ }
+ /* still in abandoned array, so delete */
+ ret = ldap_int_bisect_delete( &ld->ld_abandoned, &ld->ld_nabandoned,
msgid, idx );
+ LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
+ return ret;
}