]> 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 5ef2eaae896ba1d1e3db6ea794c042ac40e4903b..2ac8425017b4a9c01e1bf641e39af7853b1ccb55 100644 (file)
@@ -790,7 +790,7 @@ static int dec_mutexint( mutexint *mi )
        return i;
 }
 
-static void
+static int
 syncprov_free_syncop( syncops *so )
 {
        syncres *sr, *srnext;
@@ -800,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 ) {
@@ -824,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 */
@@ -1104,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
@@ -1166,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;
@@ -1229,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;
 
@@ -1266,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;
                }
 
@@ -1310,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",
@@ -1342,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 );