#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,
return rc;
}
+/* protected by res_mutex */
static LDAPMessage *
chkResponseList(
LDAP *ld,
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;
}
return lm;
}
+/* protected by res_mutex */
static int
wait4msg(
LDAP *ld,
if ( ldap_debug & LDAP_DEBUG_TRACE ) {
Debug( LDAP_DEBUG_TRACE, "wait4msg continue ld %p msgid %d all %d\n",
(void *)ld, msgid, all );
- LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
ldap_dump_connection( ld, ld->ld_conns, 1 );
- LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
ldap_dump_requests_and_responses( ld );
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
break;
}
}
- LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
if ( !lc_ready ) {
int err;
{
ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN :
LDAP_TIMEOUT);
+ LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
return( rc );
}
{
ldap_int_flush_request( ld, ld->ld_requests );
}
- LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
- LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
for ( lc = ld->ld_conns;
rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL;
lc = lnext )
{
/* Don't let it get freed out from under us */
++lc->lconn_refcnt;
- LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
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_MUTEX_LOCK( &ld->ld_req_mutex );
ldap_free_connection( ld, lc, 0, 1 );
- LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
} else {
--lc->lconn_refcnt;
}
- LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
} else {
lnext = lc->lconn_next;
}
}
- LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
+ LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
}
+ LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
}
if ( rc == LDAP_MSG_X_KEEP_LOOKING && tvp != NULL ) {
}
+/* protected by res_mutex, conn_mutex and req_mutex */
static ber_tag_t
try_read1msg(
LDAP *ld,
BerElement *ber;
LDAPMessage *newmsg, *l, *prev;
ber_int_t id;
- int idx;
ber_tag_t tag;
ber_len_t len;
int foundit = 0;
assert( lc != NULL );
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 );
/* 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;
}
*
* 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 )
{
- LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
-
- assert( idxp != NULL );
+ int ret, idx;
assert( msgid >= 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 )
{
- LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
+ int ret, idx;
- /* NOTE: those assertions are repeated in ldap_int_bisect_delete() */
- assert( idx >= 0 );
- assert( (unsigned) idx < ld->ld_nabandoned );
- assert( ld->ld_abandoned[ idx ] == msgid );
-
- 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;
}