connection_abandon( c );
/* wake write blocked operations */
- slapd_clr_write( sd, 1 );
if ( c->c_writewaiter ) {
ldap_pvt_thread_cond_signal( &c->c_write_cv );
+ /* ITS#4667 this may allow another thread to drop into
+ * connection_resched / connection_close before we
+ * finish, but that's OK.
+ */
+ slapd_clr_write( sd, 1 );
+ ldap_pvt_thread_mutex_unlock( &c->c_mutex );
+ ldap_pvt_thread_mutex_lock( &c->c_write_mutex );
+ ldap_pvt_thread_mutex_lock( &c->c_mutex );
+ ldap_pvt_thread_mutex_unlock( &c->c_write_mutex );
+ } else {
+ slapd_clr_write( sd, 1 );
}
} else if( why == NULL && c->c_close_reason == conn_lost_str ) {
assert( connections != NULL );
assert( c != NULL );
+
+ /* ITS#4667 we may have gotten here twice */
+ if ( c->c_conn_state == SLAP_C_INVALID )
+ return;
+
assert( c->c_struct_state == SLAP_C_USED );
assert( c->c_conn_state == SLAP_C_CLOSING );
ldap_pvt_thread_mutex_lock( &connections_mutex );
for(; *index < dtblsize; (*index)++) {
+ int c_struct;
if( connections[*index].c_struct_state == SLAP_C_UNINITIALIZED ) {
assert( connections[*index].c_conn_state == SLAP_C_INVALID );
+#ifdef HAVE_WINSOCK
break;
+#else
+ continue;
+#endif
}
if( connections[*index].c_struct_state == SLAP_C_USED ) {
break;
}
- assert( connections[*index].c_struct_state == SLAP_C_UNUSED );
+ c_struct = connections[*index].c_struct_state;
+ if ( c_struct == SLAP_C_PENDING )
+ continue;
+ assert( c_struct == SLAP_C_UNUSED );
assert( connections[*index].c_conn_state == SLAP_C_INVALID );
}
Operation *op = arg_v;
SlapReply rs = {REP_RESULT};
ber_tag_t tag = op->o_tag;
- int opidx = -1;
+ slap_op_t opidx = SLAP_OP_LAST;
Connection *conn = op->o_conn;
void *memctx = NULL;
void *memctx_null = NULL;
}
}
- switch ( tag ) {
- case LDAP_REQ_BIND:
- opidx = SLAP_OP_BIND;
- break;
-
- case LDAP_REQ_UNBIND:
- opidx = SLAP_OP_UNBIND;
- break;
-
- case LDAP_REQ_ADD:
- opidx = SLAP_OP_ADD;
- break;
-
- case LDAP_REQ_DELETE:
- opidx = SLAP_OP_DELETE;
- break;
-
- case LDAP_REQ_MODRDN:
- opidx = SLAP_OP_MODRDN;
- break;
-
- case LDAP_REQ_MODIFY:
- opidx = SLAP_OP_MODIFY;
- break;
-
- case LDAP_REQ_COMPARE:
- opidx = SLAP_OP_COMPARE;
- break;
-
- case LDAP_REQ_SEARCH:
- opidx = SLAP_OP_SEARCH;
- break;
-
- case LDAP_REQ_ABANDON:
- opidx = SLAP_OP_ABANDON;
- break;
-
- case LDAP_REQ_EXTENDED:
- opidx = SLAP_OP_EXTENDED;
- break;
-
- default:
- /* not reachable */
- assert( 0 );
- }
-
- assert( opidx > -1 );
+ opidx = slap_req2op( tag );
+ assert( opidx != SLAP_OP_LAST );
INCR_OP_INITIATED( opidx );
rc = (*(opfun[opidx]))( op, &rs );
if ( rc == SLAPD_DISCONNECT ) {
tag = LBER_ERROR;
- } else if ( opidx > -1 ) {
+ } else if ( opidx != SLAP_OP_LAST ) {
/* increment completed operations count
* only if operation was initiated
* and rc != SLAPD_DISCONNECT */
return -1;
}
- errno = 0;
+ sock_errset(0);
#ifdef LDAP_CONNECTIONLESS
if ( conn->c_is_udp ) {
tag = ber_get_next( conn->c_sb, &len, conn->c_currentber );
if ( tag != LDAP_TAG_MESSAGE ) {
- int err = errno;
+ int err = sock_errno();
ber_socket_t sd;
ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
static int connection_bind_cb( Operation *op, SlapReply *rs )
{
ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
- op->o_conn->c_conn_state = SLAP_C_ACTIVE;
+ if ( op->o_conn->c_conn_state == SLAP_C_BINDING )
+ op->o_conn->c_conn_state = SLAP_C_ACTIVE;
op->o_conn->c_sasl_bind_in_progress =
( rs->sr_err == LDAP_SASL_BIND_IN_PROGRESS );