]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/syncprov.c
ITS#5452,#8012: fix syncprov syncops freeing
[openldap] / servers / slapd / overlays / syncprov.c
index dd8229fcba520ea1c97537361279429e16c25ef5..2ac8425017b4a9c01e1bf641e39af7853b1ccb55 100644 (file)
@@ -2,7 +2,7 @@
 /* syncprov.c - syncrepl provider */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2004-2013 The OpenLDAP Foundation.
+ * Copyright 2004-2014 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -28,9 +28,7 @@
 #include "config.h"
 #include "ldap_rq.h"
 
-#ifdef LDAP_DEVEL
 #define        CHECK_CSN       1
-#endif
 
 /* A modify request on a particular entry */
 typedef struct modinst {
@@ -444,6 +442,7 @@ syncprov_findbase( Operation *op, fbase_cookie *fc )
                fop.o_hdr = op->o_hdr;
                fop.o_time = op->o_time;
                fop.o_tincr = op->o_tincr;
+               fop.o_extra = op->o_extra;
 
                cb.sc_response = findbase_cb;
                cb.sc_private = fc;
@@ -451,7 +450,6 @@ syncprov_findbase( Operation *op, fbase_cookie *fc )
                fop.o_sync_mode = 0;    /* turn off sync mode */
                fop.o_managedsait = SLAP_CONTROL_CRITICAL;
                fop.o_callback = &cb;
-               LDAP_SLIST_INIT( &fop.o_extra );
                fop.o_tag = LDAP_REQ_SEARCH;
                fop.ors_scope = LDAP_SCOPE_BASE;
                fop.ors_limit = NULL;
@@ -792,7 +790,7 @@ static int dec_mutexint( mutexint *mi )
        return i;
 }
 
-static void
+static int
 syncprov_free_syncop( syncops *so )
 {
        syncres *sr, *srnext;
@@ -802,7 +800,7 @@ syncprov_free_syncop( syncops *so )
        /* already being freed, or still in use */
        if ( !so->s_inuse || --so->s_inuse > 0 ) {
                ldap_pvt_thread_mutex_unlock( &so->s_mutex );
-               return;
+               return 0;
        }
        ldap_pvt_thread_mutex_unlock( &so->s_mutex );
        if ( so->s_flags & PS_IS_DETACHED ) {
@@ -826,6 +824,7 @@ syncprov_free_syncop( syncops *so )
        }
        ldap_pvt_thread_mutex_destroy( &so->s_mutex );
        ch_free( so );
+       return 1;
 }
 
 /* Send a persistent search response */
@@ -1106,9 +1105,7 @@ syncprov_drop_psearch( syncops *so, int lock )
                if ( lock )
                        ldap_pvt_thread_mutex_unlock( &so->s_op->o_conn->c_mutex );
        }
-       syncprov_free_syncop( so );
-
-       return 0;
+       return syncprov_free_syncop( so );
 }
 
 static int
@@ -1116,7 +1113,7 @@ syncprov_ab_cleanup( Operation *op, SlapReply *rs )
 {
        slap_callback *sc = op->o_callback;
        op->o_callback = sc->sc_next;
-       syncprov_drop_psearch( op->o_callback->sc_private, 0 );
+       syncprov_drop_psearch( sc->sc_private, 0 );
        op->o_tmpfree( sc, op->o_tmpmemctx );
        return 0;
 }
@@ -1168,10 +1165,10 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
        syncprov_info_t         *si = on->on_bi.bi_private;
 
        fbase_cookie fc;
-       syncops *ss, *sprev, *snext;
+       syncops **pss;
        Entry *e = NULL;
        Attribute *a;
-       int rc;
+       int rc, gonext;
        struct berval newdn;
        int freefdn = 0;
        BackendDB *b0 = op->o_bd, db;
@@ -1231,15 +1228,15 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
        }
 
        ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
-       for (ss = si->si_ops, sprev = (syncops *)&si->si_ops; ss;
-               sprev = ss, ss=snext)
+       for (pss = &si->si_ops; *pss; pss = gonext ? &(*pss)->s_next : pss)
        {
                Operation op2;
                Opheader oh;
                syncmatches *sm;
                int found = 0;
+               syncops *snext, *ss = *pss;
 
-               snext = ss->s_next;
+               gonext = 1;
                if ( ss->s_op->o_abandon )
                        continue;
 
@@ -1268,9 +1265,10 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
                        SlapReply rs = {REP_RESULT};
                        send_ldap_error( ss->s_op, &rs, LDAP_SYNC_REFRESH_REQUIRED,
                                "search base has changed" );
-                       sprev->s_next = snext;
-                       syncprov_drop_psearch( ss, 1 );
-                       ss = sprev;
+                       snext = ss->s_next;
+                       if ( syncprov_drop_psearch( ss, 1 ) )
+                               *pss = snext;
+                       gonext = 0;
                        continue;
                }
 
@@ -1312,8 +1310,8 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
                                   phase otherwise (ITS#6555) */
                                op2.ors_filter = ss->s_op->ors_filter->f_and->f_next;
                        }
-                       ldap_pvt_thread_mutex_unlock( &ss->s_mutex );
                        rc = test_filter( &op2, e, op2.ors_filter );
+                       ldap_pvt_thread_mutex_unlock( &ss->s_mutex );
                }
 
                Debug( LDAP_DEBUG_TRACE, "syncprov_matchops: sid %03x fscope %d rc %d\n",
@@ -1344,7 +1342,11 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
                        /* Decrement s_inuse, was incremented when called
                         * with saveit == TRUE
                         */
-                       syncprov_free_syncop( ss );
+                       snext = ss->s_next;
+                       if ( syncprov_free_syncop( ss ) ) {
+                               *pss = snext;
+                               gonext = 0;
+                       }
                }
        }
        ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex );
@@ -3172,6 +3174,7 @@ syncprov_db_close(
 
 #ifdef SLAP_CONFIG_DELETE
        if ( !slapd_shutdown ) {
+               ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
                for ( so=si->si_ops, sonext=so;  so; so=sonext  ) {
                        SlapReply rs = {REP_RESULT};
                        rs.sr_err = LDAP_UNAVAILABLE;
@@ -3180,6 +3183,7 @@ syncprov_db_close(
                        syncprov_drop_psearch( so, 0);
                }
                si->si_ops=NULL;
+               ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex );
        }
        overlay_unregister_control( be, LDAP_CONTROL_SYNC );
 #endif /* SLAP_CONFIG_DELETE */