From: Quanah Gibson-Mount Date: Fri, 5 Jun 2009 01:19:17 +0000 (+0000) Subject: ITS#6157 X-Git-Tag: OPENLDAP_REL_ENG_2_4_17~55 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=a1563dcb742a825705fffe6706dfd8e80f664a11;p=openldap ITS#6157 --- diff --git a/CHANGES b/CHANGES index ab1fb801b8..604b8506ca 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,7 @@ OpenLDAP 2.4.17 Engineering Added slapd sasl auxprop support (ITS#6147) Added slapd schema checking tool (ITS#6150) Added slapd writetimeout keyword (ITS#5836) + Fixed slapd abandon/cancel handling for some ops (ITS#6157) Fixed slapd assert with closing connections (ITS#6111) Fixed slapd cancel behavior (ITS#6137) Fixed slapd cert validation (ITS#6098) diff --git a/servers/slapd/abandon.c b/servers/slapd/abandon.c index 8e08707756..8b0156902c 100644 --- a/servers/slapd/abandon.c +++ b/servers/slapd/abandon.c @@ -96,6 +96,17 @@ do_abandon( Operation *op, SlapReply *rs ) break; } } + + } else if ( o->o_tag == LDAP_REQ_BIND + || o->o_tag == LDAP_REQ_UNBIND + || o->o_tag == LDAP_REQ_ABANDON ) { + msg = "cannot be abandoned"; + +#if 0 /* Would break o_abandon used as "suppress response" flag, ITS#6138 */ + } else if ( o->o_abandon ) { + msg = "already being abandoned"; +#endif + } else { msg = "found"; /* Set the o_abandon flag in the to-be-abandoned operation. diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index bb59aa6969..c1fea158b9 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -4783,6 +4783,10 @@ config_back_add( Operation *op, SlapReply *rs ) } } + if ( op->o_abandon ) { + rs->sr_err = SLAPD_ABANDON; + goto out; + } ldap_pvt_thread_pool_pause( &connection_pool ); /* Strategy: @@ -5223,8 +5227,13 @@ config_back_modify( Operation *op, SlapReply *rs ) slap_mods_opattrs( op, &op->orm_modlist, 1 ); - if ( do_pause ) + if ( do_pause ) { + if ( op->o_abandon ) { + rs->sr_err = SLAPD_ABANDON; + goto out; + } ldap_pvt_thread_pool_pause( &connection_pool ); + } /* Strategy: * 1) perform the Modify on the cached Entry. @@ -5388,6 +5397,10 @@ config_back_modrdn( Operation *op, SlapReply *rs ) goto out; } + if ( op->o_abandon ) { + rs->sr_err = SLAPD_ABANDON; + goto out; + } ldap_pvt_thread_pool_pause( &connection_pool ); if ( ce->ce_type == Cft_Schema ) { @@ -5477,6 +5490,8 @@ config_back_delete( Operation *op, SlapReply *rs ) rs->sr_err = LDAP_NO_SUCH_OBJECT; } else if ( ce->ce_kids ) { rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + } else if ( op->o_abandon ) { + rs->sr_err = SLAPD_ABANDON; } else if ( ce->ce_type == Cft_Overlay ){ char *iptr; int count, ixold; diff --git a/servers/slapd/cancel.c b/servers/slapd/cancel.c index 5e65e090db..6d27d1756a 100644 --- a/servers/slapd/cancel.c +++ b/servers/slapd/cancel.c @@ -66,16 +66,25 @@ int cancel_extop( Operation *op, SlapReply *rs ) ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); + if ( op->o_abandon ) { + /* FIXME: Should instead reject the cancel/abandon of this op, but + * it seems unsafe to reset op->o_abandon once it is set. ITS#6138. + */ + rc = LDAP_OPERATIONS_ERROR; + rs->sr_text = "tried to abandon or cancel this operation"; + goto out; + } + LDAP_STAILQ_FOREACH( o, &op->o_conn->c_pending_ops, o_next ) { if ( o->o_msgid == opid ) { - ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); /* TODO: We could instead remove the cancelled operation * from c_pending_ops like Abandon does, and send its * response here. Not if it is pending because of a * congested connection though. */ + rc = LDAP_CANNOT_CANCEL; rs->sr_text = "too busy for Cancel, try Abandon instead"; - return LDAP_CANNOT_CANCEL; + goto out; } } @@ -88,15 +97,31 @@ int cancel_extop( Operation *op, SlapReply *rs ) if ( o == NULL ) { rc = LDAP_NO_SUCH_OPERATION; rs->sr_text = "message ID not found"; + + } else if ( o->o_tag == LDAP_REQ_BIND + || o->o_tag == LDAP_REQ_UNBIND + || o->o_tag == LDAP_REQ_ABANDON ) { + rc = LDAP_CANNOT_CANCEL; + } else if ( o->o_cancel != SLAP_CANCEL_NONE ) { - rc = LDAP_PROTOCOL_ERROR; + rc = LDAP_OPERATIONS_ERROR; rs->sr_text = "message ID already being cancelled"; + +#if 0 + } else if ( o->o_abandon ) { + /* TODO: Would this break something when + * o_abandon="suppress response"? (ITS#6138) + */ + rc = LDAP_TOO_LATE; +#endif + } else { rc = LDAP_SUCCESS; o->o_cancel = SLAP_CANCEL_REQ; o->o_abandon = 1; } + out: ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); if ( rc == LDAP_SUCCESS ) { @@ -109,14 +134,12 @@ int cancel_extop( Operation *op, SlapReply *rs ) } } - while ( o->o_cancel == SLAP_CANCEL_REQ ) { + while ( (rc = o->o_cancel) == SLAP_CANCEL_REQ ) { ldap_pvt_thread_yield(); } - if ( o->o_cancel == SLAP_CANCEL_ACK ) { + if ( rc == SLAP_CANCEL_ACK ) { rc = LDAP_SUCCESS; - } else { - rc = o->o_cancel; } o->o_cancel = SLAP_CANCEL_DONE;