]> git.sur5r.net Git - openldap/commitdiff
More ITS#6104: mutex-protected check of o_cancel value from other thread
authorHallvard Furuseth <hallvard@openldap.org>
Fri, 5 Jun 2009 23:26:09 +0000 (23:26 +0000)
committerHallvard Furuseth <hallvard@openldap.org>
Fri, 5 Jun 2009 23:26:09 +0000 (23:26 +0000)
servers/slapd/cancel.c
servers/slapd/connection.c

index 6d27d1756a5b32fe4f6ab674bbcf2687838bc738..935a67b1a1fb38ddf970a8c97facd2ccbeeca6c8 100644 (file)
@@ -134,9 +134,16 @@ int cancel_extop( Operation *op, SlapReply *rs )
                        }
                }
 
-               while ( (rc = o->o_cancel) == SLAP_CANCEL_REQ ) {
-                       ldap_pvt_thread_yield();
-               }
+               do {
+                       /* Fake a cond_wait with thread_yield, then
+                        * verify the result properly mutex-protected.
+                        */
+                       while ( o->o_cancel == SLAP_CANCEL_REQ )
+                               ldap_pvt_thread_yield();
+                       ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
+                       rc = o->o_cancel;
+                       ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
+               } while ( rc == SLAP_CANCEL_REQ );
 
                if ( rc == SLAP_CANCEL_ACK ) {
                        rc = LDAP_SUCCESS;
index bf7f68c1ce1073b3f081bcc8315f870d6051c23f..cb818a4a9edb6029fe7827928de8c8433098047e 100644 (file)
@@ -1021,7 +1021,7 @@ conn_counter_init( Operation *op, void *ctx )
 static void *
 connection_operation( void *ctx, void *arg_v )
 {
-       int rc = LDAP_OTHER;
+       int rc = LDAP_OTHER, cancel;
        Operation *op = arg_v;
        SlapReply rs = {REP_RESULT};
        ber_tag_t tag = op->o_tag;
@@ -1125,22 +1125,29 @@ operations_error:
                INCR_OP_COMPLETED( opidx );
        }
 
-       if ( op->o_cancel == SLAP_CANCEL_REQ ) {
-               if ( rc == SLAPD_ABANDON ) {
-                       op->o_cancel = SLAP_CANCEL_ACK;
-               } else {
-                       op->o_cancel = LDAP_TOO_LATE;
+       ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+
+       cancel = op->o_cancel;
+       if ( cancel != SLAP_CANCEL_NONE && cancel != SLAP_CANCEL_DONE ) {
+               if ( cancel == SLAP_CANCEL_REQ ) {
+                       op->o_cancel = rc == SLAPD_ABANDON
+                               ? SLAP_CANCEL_ACK : LDAP_TOO_LATE;
                }
-       }
 
-       while ( op->o_cancel != SLAP_CANCEL_NONE &&
-               op->o_cancel != SLAP_CANCEL_DONE )
-       {
-               ldap_pvt_thread_yield();
+               do {
+                       /* Fake a cond_wait with thread_yield, then
+                        * verify the result properly mutex-protected.
+                        */
+                       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+                       do {
+                               ldap_pvt_thread_yield();
+                       } while ( (cancel = op->o_cancel) != SLAP_CANCEL_NONE
+                                       && cancel != SLAP_CANCEL_DONE );
+                       ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+               } while ( (cancel = op->o_cancel) != SLAP_CANCEL_NONE
+                               && cancel != SLAP_CANCEL_DONE );
        }
 
-       ldap_pvt_thread_mutex_lock( &conn->c_mutex );
-
        ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx_null );
 
        LDAP_STAILQ_REMOVE( &conn->c_ops, op, Operation, o_next);