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 );
}
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 );