"connid=%lu msgid=%d invalid integer sent in abandon request\n",
c->c_connid, op->o_client_msgid );
- CONNECTION_UNLOCK_INCREF(c);
- operation_send_reject(
- op, LDAP_PROTOCOL_ERROR, "invalid PDU received", 0 );
- CONNECTION_LOCK_DECREF(c);
- CONNECTION_DESTROY(c);
+ if ( operation_send_reject_locked( op, LDAP_PROTOCOL_ERROR,
+ "invalid PDU received", 0 ) == LDAP_SUCCESS ) {
+ CONNECTION_DESTROY(c);
+ }
return -1;
}
return rc;
}
-void
-operation_send_reject(
+/*
+ * Called with op->o_client non-NULL and already locked.
+ */
+int
+operation_send_reject_locked(
Operation *op,
int result,
const char *msg,
int send_anyway )
{
- Connection *c;
+ Connection *c = op->o_client;
BerElement *ber;
int found;
- Debug( LDAP_DEBUG_TRACE, "operation_send_reject: "
+ Debug( LDAP_DEBUG_TRACE, "operation_send_reject_locked: "
"rejecting %s from client connid=%lu with message: \"%s\"\n",
- slap_msgtype2str( op->o_tag ), op->o_client_connid, msg );
-
- ldap_pvt_thread_mutex_lock( &op->o_link_mutex );
- c = op->o_client;
- if ( !c ) {
- c = op->o_upstream;
- /* One of the connections has initiated this and keeps a reference, if
- * client is dead, it must have been the upstream */
- assert( c );
- CONNECTION_LOCK(c);
- ldap_pvt_thread_mutex_unlock( &op->o_link_mutex );
- Debug( LDAP_DEBUG_TRACE, "operation_send_reject: "
- "not sending msgid=%d, client connid=%lu is dead\n",
- op->o_client_msgid, op->o_client_connid );
- operation_destroy_from_upstream( op );
- CONNECTION_UNLOCK_OR_DESTROY(c);
- return;
- }
- CONNECTION_LOCK(c);
- ldap_pvt_thread_mutex_unlock( &op->o_link_mutex );
+ slap_msgtype2str( op->o_tag ), c->c_connid, msg );
found = ( tavl_delete( &c->c_ops, op, operation_client_cmp ) == op );
if ( !found && !send_anyway ) {
- Debug( LDAP_DEBUG_TRACE, "operation_send_reject: "
+ Debug( LDAP_DEBUG_TRACE, "operation_send_reject_locked: "
"msgid=%d not scheduled for client connid=%lu anymore, "
"not sending\n",
op->o_client_msgid, c->c_connid );
ber = c->c_pendingber;
if ( ber == NULL && (ber = ber_alloc()) == NULL ) {
ldap_pvt_thread_mutex_unlock( &c->c_io_mutex );
- Debug( LDAP_DEBUG_ANY, "operation_send_reject: "
+ Debug( LDAP_DEBUG_ANY, "operation_send_reject_locked: "
"ber_alloc failed, closing connid=%lu\n",
c->c_connid );
CONNECTION_LOCK_DECREF(c);
operation_destroy_from_client( op );
CONNECTION_DESTROY(c);
- return;
+ return -1;
}
c->c_pendingber = ber;
CONNECTION_LOCK_DECREF(c);
done:
operation_destroy_from_client( op );
- CONNECTION_UNLOCK_OR_DESTROY(c);
+ return LDAP_SUCCESS;
+}
+
+void
+operation_send_reject(
+ Operation *op,
+ int result,
+ const char *msg,
+ int send_anyway )
+{
+ Connection *c;
+
+ ldap_pvt_thread_mutex_lock( &op->o_link_mutex );
+ c = op->o_client;
+ if ( !c ) {
+ c = op->o_upstream;
+ /* One of the connections has initiated this and keeps a reference, if
+ * client is dead, it must have been the upstream */
+ assert( c );
+ CONNECTION_LOCK(c);
+ ldap_pvt_thread_mutex_unlock( &op->o_link_mutex );
+ Debug( LDAP_DEBUG_TRACE, "operation_send_reject: "
+ "not sending msgid=%d, client connid=%lu is dead\n",
+ op->o_client_msgid, op->o_client_connid );
+ operation_destroy_from_upstream( op );
+ CONNECTION_UNLOCK_OR_DESTROY(c);
+ return;
+ }
+ CONNECTION_LOCK(c);
+ ldap_pvt_thread_mutex_unlock( &op->o_link_mutex );
+
+ /* Non-zero return means connection has been unlocked and might be
+ * destroyed */
+ if ( operation_send_reject_locked( op, result, msg, send_anyway ) ==
+ LDAP_SUCCESS ) {
+ CONNECTION_UNLOCK_OR_DESTROY(c);
+ }
}
/*