Blame SOURCES/0061-Ticket-48005-ns-slapd-crash-in-shutdown-phase.patch

309aa9
From 2e87dafa9d39e6ab08382612be762c25afa80d4f Mon Sep 17 00:00:00 2001
309aa9
From: Noriko Hosoi <nhosoi@redhat.com>
309aa9
Date: Sun, 15 Feb 2015 17:34:12 -0800
309aa9
Subject: [PATCH] Ticket #48005 - ns-slapd crash in shutdown phase
309aa9
309aa9
Description: There was a small window that long running tasks access its
309aa9
own task object after it's aready released by main thread in the shutdown
309aa9
period.  This patch adds refcounter to such threads and make destructor
309aa9
wait until the counter becomes 0.  Plus, the shutdown check is added to
309aa9
their task callbacks.
309aa9
309aa9
Following tasks are updated by this patch:
309aa9
  slapd/task.c:                         "fixup tombstones"
309aa9
  posix-winsync/posix-winsync-config.c: "memberuid task"
309aa9
  replication/repl5_replica_config.c:   "cleanallruv"
309aa9
  replication/repl5_replica_config.c:   "abort cleanallruv"
309aa9
  syntaxes/validate_task.c:             "syntax validate"
309aa9
  automember/automember.c:              "automember rebuild membership"
309aa9
  automember/automember.c:              "automember export updates"
309aa9
  automember/automember.c:              "automember map updates"
309aa9
  linkedattrs/linked_attrs.c:           "fixup linked attributes"
309aa9
  memberof/memberof.c:                  "memberof task"
309aa9
  schema_reload/schema_reload.c:        "schema reload task"
309aa9
  usn/usn_cleanup.c:                    "USN tombstone cleanup task"
309aa9
309aa9
Following tasks are already covered:
309aa9
  slapd/task.c: "import"
309aa9
  slapd/task.c: "index"
309aa9
  slapd/task.c: "upgradedb"
309aa9
309aa9
Following tasks are processed in an ordinary worker thread; no need to change
309aa9
  slapd/task.c: "sysconfig reload"
309aa9
  slapd/task.c: "export"
309aa9
  slapd/task.c: "backup"
309aa9
  slapd/task.c: "restore"
309aa9
309aa9
(cherry picked from commit ab2e26de21beb5a92d2a18ab5a20db9637b83c7a)
309aa9
(cherry picked from commit eebbabbaba8f024671158f527a169fc378ff01d6)
309aa9
309aa9
Conflicts:
309aa9
	ldap/servers/plugins/memberof/memberof.c
309aa9
---
309aa9
 ldap/servers/plugins/automember/automember.c       | 70 ++++++++++++++++++----
309aa9
 ldap/servers/plugins/linkedattrs/fixup_task.c      | 40 +++++++++++--
309aa9
 ldap/servers/plugins/memberof/memberof.c           | 26 +++++++-
309aa9
 ldap/servers/plugins/memberof/memberof.h           |  2 +-
309aa9
 .../plugins/posix-winsync/posix-group-task.c       | 40 ++++++++++---
309aa9
 .../plugins/replication/repl5_replica_config.c     | 58 ++++++++++++++++++
309aa9
 ldap/servers/plugins/schema_reload/schema_reload.c | 23 ++++++-
309aa9
 ldap/servers/plugins/syntaxes/validate_task.c      | 26 +++++++-
309aa9
 ldap/servers/plugins/usn/usn_cleanup.c             | 58 +++++++++++++-----
309aa9
 ldap/servers/slapd/slapi-plugin.h                  |  9 +++
309aa9
 ldap/servers/slapd/slapi-private.h                 |  2 -
309aa9
 ldap/servers/slapd/task.c                          | 47 +++++++++++++--
309aa9
 12 files changed, 348 insertions(+), 53 deletions(-)
309aa9
309aa9
diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c
309aa9
index 6a8fd22..b2914db 100644
309aa9
--- a/ldap/servers/plugins/automember/automember.c
309aa9
+++ b/ldap/servers/plugins/automember/automember.c
309aa9
@@ -119,9 +119,9 @@ static int automember_task_add_map_entries(Slapi_PBlock *pb, Slapi_Entry *e, Sla
309aa9
 void automember_rebuild_task_thread(void *arg);
309aa9
 void automember_export_task_thread(void *arg);
309aa9
 void automember_map_task_thread(void *arg);
309aa9
-void automember_task_destructor(Slapi_Task *task);
309aa9
-void automember_task_export_destructor(Slapi_Task *task);
309aa9
-void automember_task_map_destructor(Slapi_Task *task);
309aa9
+static void automember_task_destructor(Slapi_Task *task);
309aa9
+static void automember_task_export_destructor(Slapi_Task *task);
309aa9
+static void automember_task_map_destructor(Slapi_Task *task);
309aa9
 
309aa9
 #define DEFAULT_FILE_MODE PR_IRUSR | PR_IWUSR
309aa9
 
309aa9
@@ -1962,11 +1962,15 @@ fetch_attr(Slapi_Entry *e, const char *attrname, const char *default_val)
309aa9
     return slapi_value_get_string(val);
309aa9
 }
309aa9
 
309aa9
-void
309aa9
+static void
309aa9
 automember_task_destructor(Slapi_Task *task)
309aa9
 {
309aa9
     if (task) {
309aa9
         task_data *mydata = (task_data *)slapi_task_get_data(task);
309aa9
+		while (slapi_task_get_refcount(task) > 0) {
309aa9
+			/* Yield to wait for the fixup task finishes. */
309aa9
+			DS_Sleep (PR_MillisecondsToInterval(100));
309aa9
+		}
309aa9
         if (mydata) {
309aa9
             slapi_ch_free_string(&mydata->bind_dn);
309aa9
             slapi_sdn_free(&mydata->base_dn);
309aa9
@@ -1976,11 +1980,15 @@ automember_task_destructor(Slapi_Task *task)
309aa9
     }
309aa9
 }
309aa9
 
309aa9
-void
309aa9
+static void
309aa9
 automember_task_export_destructor(Slapi_Task *task)
309aa9
 {
309aa9
     if (task) {
309aa9
         task_data *mydata = (task_data *)slapi_task_get_data(task);
309aa9
+		while (slapi_task_get_refcount(task) > 0) {
309aa9
+			/* Yield to wait for the fixup task finishes. */
309aa9
+			DS_Sleep (PR_MillisecondsToInterval(100));
309aa9
+		}
309aa9
         if (mydata) {
309aa9
             slapi_ch_free_string(&mydata->ldif_out);
309aa9
             slapi_ch_free_string(&mydata->bind_dn);
309aa9
@@ -1991,11 +1999,15 @@ automember_task_export_destructor(Slapi_Task *task)
309aa9
     }
309aa9
 }
309aa9
 
309aa9
-void
309aa9
+static void
309aa9
 automember_task_map_destructor(Slapi_Task *task)
309aa9
 {
309aa9
     if (task) {
309aa9
         task_data *mydata = (task_data *)slapi_task_get_data(task);
309aa9
+		while (slapi_task_get_refcount(task) > 0) {
309aa9
+			/* Yield to wait for the fixup task finishes. */
309aa9
+			DS_Sleep (PR_MillisecondsToInterval(100));
309aa9
+		}
309aa9
         if (mydata) {
309aa9
             slapi_ch_free_string(&mydata->ldif_out);
309aa9
             slapi_ch_free_string(&mydata->ldif_in);
309aa9
@@ -2114,7 +2126,8 @@ out:
309aa9
  *  Search using the basedn, filter, and scope provided from the task data.
309aa9
  *  Then loop of each entry, and apply the membership if applicable.
309aa9
  */
309aa9
-void automember_rebuild_task_thread(void *arg){
309aa9
+void automember_rebuild_task_thread(void *arg)
309aa9
+{
309aa9
     Slapi_Task *task = (Slapi_Task *)arg;
309aa9
     struct configEntry *config = NULL;
309aa9
     Slapi_PBlock *search_pb = NULL, *fixup_pb = NULL;
309aa9
@@ -2124,6 +2137,12 @@ void automember_rebuild_task_thread(void *arg){
309aa9
     int result = 0;
309aa9
     int i = 0;
309aa9
 
309aa9
+    if (!task) {
309aa9
+        return; /* no task */
309aa9
+    }
309aa9
+    slapi_task_inc_refcount(task);
309aa9
+    slapi_log_error( SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
309aa9
+                     "automember_rebuild_task_thread --> refcount incremented.\n" );
309aa9
     /*
309aa9
      *  Fetch our task data from the task
309aa9
      */
309aa9
@@ -2192,7 +2211,8 @@ void automember_rebuild_task_thread(void *arg){
309aa9
                 if (slapi_dn_issuffix(slapi_entry_get_dn(entries[i]), config->scope) &&
309aa9
                     (slapi_filter_test_simple(entries[i], config->filter) == 0))
309aa9
                 {
309aa9
-                    if(automember_update_membership(config, entries[i], NULL)){
309aa9
+                    if (slapi_is_shutting_down() ||
309aa9
+                        automember_update_membership(config, entries[i], NULL)) {
309aa9
                         result = SLAPI_PLUGIN_FAILURE;
309aa9
                         automember_config_unlock();
309aa9
                         goto out;
309aa9
@@ -2226,6 +2246,9 @@ out:
309aa9
     }
309aa9
     slapi_task_inc_progress(task);
309aa9
     slapi_task_finish(task, result);
309aa9
+    slapi_task_dec_refcount(task);
309aa9
+    slapi_log_error( SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
309aa9
+                     "automember_rebuild_task_thread <-- refcount decremented.\n" );
309aa9
 }
309aa9
 
309aa9
 /*
309aa9
@@ -2328,7 +2351,8 @@ out:
309aa9
     return rv;
309aa9
 }
309aa9
 
309aa9
-void automember_export_task_thread(void *arg){
309aa9
+void automember_export_task_thread(void *arg)
309aa9
+{
309aa9
     Slapi_Task *task = (Slapi_Task *)arg;
309aa9
     Slapi_PBlock *search_pb = NULL;
309aa9
     Slapi_Entry **entries = NULL;
309aa9
@@ -2340,6 +2364,13 @@ void automember_export_task_thread(void *arg){
309aa9
     int i = 0;
309aa9
     int rc = 0;
309aa9
 
309aa9
+    if (!task) {
309aa9
+        return; /* no task */
309aa9
+    }
309aa9
+    slapi_task_inc_refcount(task);
309aa9
+    slapi_log_error( SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
309aa9
+                     "automember_export_task_thread --> refcount incremented.\n" );
309aa9
+
309aa9
     td = (task_data *)slapi_task_get_data(task);
309aa9
     slapi_task_begin(task, 1);
309aa9
     slapi_task_log_notice(task, "Automember export task starting.  Exporting changes to (%s)", td->ldif_out);
309aa9
@@ -2394,7 +2425,8 @@ void automember_export_task_thread(void *arg){
309aa9
                 if (slapi_dn_issuffix(slapi_sdn_get_dn(td->base_dn), config->scope) &&
309aa9
                     (slapi_filter_test_simple(entries[i], config->filter) == 0))
309aa9
                 { 
309aa9
-                    if(automember_update_membership(config, entries[i], ldif_fd)){
309aa9
+                    if (slapi_is_shutting_down() ||
309aa9
+                        automember_update_membership(config, entries[i], ldif_fd)) {
309aa9
                         result = SLAPI_DSE_CALLBACK_ERROR;
309aa9
                         automember_config_unlock();
309aa9
                         goto out;
309aa9
@@ -2423,6 +2455,9 @@ out:
309aa9
     }
309aa9
     slapi_task_inc_progress(task);
309aa9
     slapi_task_finish(task, result);
309aa9
+    slapi_task_dec_refcount(task);
309aa9
+    slapi_log_error( SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
309aa9
+                     "automember_export_task_thread <-- refcount decremented.\n" );
309aa9
 }
309aa9
 
309aa9
 /*
309aa9
@@ -2507,7 +2542,8 @@ out:
309aa9
  *  Read in the text entries from ldif_in, and convert them to slapi_entries.
309aa9
  *  Then, write to ldif_out what the updates would be if these entries were added
309aa9
  */
309aa9
-void automember_map_task_thread(void *arg){
309aa9
+void automember_map_task_thread(void *arg)
309aa9
+{
309aa9
     Slapi_Task *task = (Slapi_Task *)arg;
309aa9
     Slapi_Entry *e = NULL;
309aa9
     int result = SLAPI_DSE_CALLBACK_OK;
309aa9
@@ -2527,6 +2563,12 @@ void automember_map_task_thread(void *arg){
309aa9
 #endif
309aa9
     int rc = 0;
309aa9
 
309aa9
+    if (!task) {
309aa9
+        return; /* no task */
309aa9
+    }
309aa9
+    slapi_task_inc_refcount(task);
309aa9
+    slapi_log_error( SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
309aa9
+                     "automember_map_task_thread --> refcount incremented.\n" );
309aa9
     td = (task_data *)slapi_task_get_data(task);
309aa9
     slapi_task_begin(task, 1);
309aa9
     slapi_task_log_notice(task, "Automember map task starting...  Reading entries from (%s)"
309aa9
@@ -2586,7 +2628,8 @@ void automember_map_task_thread(void *arg){
309aa9
                     if (slapi_dn_issuffix(slapi_entry_get_dn_const(e), config->scope) &&
309aa9
                         (slapi_filter_test_simple(e, config->filter) == 0))
309aa9
                     {
309aa9
-                        if(automember_update_membership(config, e, ldif_fd_out)){
309aa9
+                        if (slapi_is_shutting_down() ||
309aa9
+                            automember_update_membership(config, e, ldif_fd_out)) {
309aa9
                             result = SLAPI_DSE_CALLBACK_ERROR;
309aa9
                             slapi_entry_free(e);
309aa9
                             slapi_ch_free_string(&entrystr);
309aa9
@@ -2620,6 +2663,9 @@ out:
309aa9
     }
309aa9
     slapi_task_inc_progress(task);
309aa9
     slapi_task_finish(task, result);
309aa9
+    slapi_task_dec_refcount(task);
309aa9
+    slapi_log_error( SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
309aa9
+                     "automember_map_task_thread <-- refcount decremented.\n" );
309aa9
 }
309aa9
 
309aa9
 /*
309aa9
diff --git a/ldap/servers/plugins/linkedattrs/fixup_task.c b/ldap/servers/plugins/linkedattrs/fixup_task.c
309aa9
index db3c693..3a01fed 100644
309aa9
--- a/ldap/servers/plugins/linkedattrs/fixup_task.c
309aa9
+++ b/ldap/servers/plugins/linkedattrs/fixup_task.c
309aa9
@@ -119,6 +119,10 @@ linked_attrs_fixup_task_destructor(Slapi_Task *task)
309aa9
 {
309aa9
 	if (task) {
309aa9
 		task_data *mydata = (task_data *)slapi_task_get_data(task);
309aa9
+		while (slapi_task_get_refcount(task) > 0) {
309aa9
+			/* Yield to wait for the fixup task finishes. */
309aa9
+			DS_Sleep (PR_MillisecondsToInterval(100));
309aa9
+		}
309aa9
 		if (mydata) {
309aa9
 			slapi_ch_free_string(&mydata->linkdn);
309aa9
 			slapi_ch_free_string(&mydata->bind_dn);
309aa9
@@ -137,6 +141,12 @@ linked_attrs_fixup_task_thread(void *arg)
309aa9
 	int found_config = 0;
309aa9
 	int rc = 0;
309aa9
 
309aa9
+	if (!task) {
309aa9
+		return; /* no task */
309aa9
+	}
309aa9
+	slapi_task_inc_refcount(task);
309aa9
+	slapi_log_error(SLAPI_LOG_PLUGIN, LINK_PLUGIN_SUBSYSTEM,
309aa9
+	                "linked_attrs_fixup_task_thread --> refcount incremented.\n" );
309aa9
 	/* Fetch our task data from the task */
309aa9
 	td = (task_data *)slapi_task_get_data(task);
309aa9
 
309aa9
@@ -154,8 +164,8 @@ linked_attrs_fixup_task_thread(void *arg)
309aa9
     linked_attrs_read_lock();
309aa9
     main_config = linked_attrs_get_config();
309aa9
     if (!PR_CLIST_IS_EMPTY(main_config)) {
309aa9
-       struct configEntry *config_entry = NULL;
309aa9
-       PRCList *list = PR_LIST_HEAD(main_config);
309aa9
+        struct configEntry *config_entry = NULL;
309aa9
+        PRCList *list = PR_LIST_HEAD(main_config);
309aa9
 
309aa9
         while (list != main_config) {
309aa9
             config_entry = (struct configEntry *) list;
309aa9
@@ -204,6 +214,10 @@ linked_attrs_fixup_task_thread(void *arg)
309aa9
 
309aa9
 	/* this will queue the destruction of the task */
309aa9
 	slapi_task_finish(task, rc);
309aa9
+
309aa9
+	slapi_task_dec_refcount(task);
309aa9
+	slapi_log_error(SLAPI_LOG_PLUGIN, LINK_PLUGIN_SUBSYSTEM,
309aa9
+	                "linked_attrs_fixup_task_thread <-- refcount decremented.\n");
309aa9
 }
309aa9
 
309aa9
 static void 
309aa9
@@ -269,7 +283,7 @@ linked_attrs_fixup_links(struct configEntry *config)
309aa9
             if(rc == 0){
309aa9
                 slapi_back_transaction_commit(fixup_pb);
309aa9
             } else {
309aa9
-            	slapi_back_transaction_abort(fixup_pb);
309aa9
+                slapi_back_transaction_abort(fixup_pb);
309aa9
             }
309aa9
             slapi_pblock_destroy(fixup_pb);
309aa9
         }
309aa9
@@ -352,11 +366,20 @@ linked_attrs_remove_backlinks_callback(Slapi_Entry *e, void *callback_data)
309aa9
     int rc = 0;
309aa9
     Slapi_DN *sdn = slapi_entry_get_sdn(e);
309aa9
     char *type = (char *)callback_data;
309aa9
-    Slapi_PBlock *pb = slapi_pblock_new();
309aa9
+    Slapi_PBlock *pb = NULL;
309aa9
     char *val[1];
309aa9
     LDAPMod mod;
309aa9
     LDAPMod *mods[2];
309aa9
 
309aa9
+    /* 
309aa9
+     * If the server is ordered to shutdown, stop the fixup and return an error.
309aa9
+     */
309aa9
+    if (slapi_is_shutting_down()) {
309aa9
+        rc = -1;
309aa9
+        goto bail;
309aa9
+    }
309aa9
+
309aa9
+    pb = slapi_pblock_new();
309aa9
     /* Remove all values of the passed in type. */
309aa9
     val[0] = 0;
309aa9
 
309aa9
@@ -377,7 +400,7 @@ linked_attrs_remove_backlinks_callback(Slapi_Entry *e, void *callback_data)
309aa9
     slapi_modify_internal_pb(pb);
309aa9
 
309aa9
     slapi_pblock_destroy(pb);
309aa9
-
309aa9
+bail:
309aa9
     return rc;
309aa9
 }
309aa9
 
309aa9
@@ -394,6 +417,13 @@ linked_attrs_add_backlinks_callback(Slapi_Entry *e, void *callback_data)
309aa9
     LDAPMod mod;
309aa9
     LDAPMod *mods[2];
309aa9
 
309aa9
+    /* 
309aa9
+     * If the server is ordered to shutdown, stop the fixup and return an error.
309aa9
+     */
309aa9
+    if (slapi_is_shutting_down()) {
309aa9
+        rc = -1;
309aa9
+        goto done;
309aa9
+    }
309aa9
     /* Setup the modify operation.  Only the target will
309aa9
      * change, so we only need to do this once. */
309aa9
     val[0] = linkdn;
309aa9
diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
309aa9
index 7e3e308..14bad98 100644
309aa9
--- a/ldap/servers/plugins/memberof/memberof.c
309aa9
+++ b/ldap/servers/plugins/memberof/memberof.c
309aa9
@@ -2636,6 +2636,12 @@ void memberof_fixup_task_thread(void *arg)
309aa9
 	int rc = 0;
309aa9
 	Slapi_PBlock *fixup_pb = NULL;
309aa9
 
309aa9
+	if (!task) {
309aa9
+		return; /* no task */
309aa9
+	}
309aa9
+	slapi_task_inc_refcount(task);
309aa9
+	slapi_log_error(SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
309aa9
+	                "memberof_fixup_task_thread --> refcount incremented.\n" );
309aa9
 	/* Fetch our task data from the task */
309aa9
 	td = (task_data *)slapi_task_get_data(task);
309aa9
 
309aa9
@@ -2702,6 +2708,9 @@ void memberof_fixup_task_thread(void *arg)
309aa9
 
309aa9
 	/* this will queue the destruction of the task */
309aa9
 	slapi_task_finish(task, rc);
309aa9
+	slapi_task_dec_refcount(task);
309aa9
+	slapi_log_error(SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
309aa9
+	                "memberof_fixup_task_thread <-- refcount decremented.\n");
309aa9
 }
309aa9
 
309aa9
 /* extract a single value from the entry (as a string) -- if it's not in the
309aa9
@@ -2793,8 +2802,14 @@ out:
309aa9
 void
309aa9
 memberof_task_destructor(Slapi_Task *task)
309aa9
 {
309aa9
+	slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
309aa9
+		"memberof_task_destructor -->\n" );
309aa9
 	if (task) {
309aa9
 		task_data *mydata = (task_data *)slapi_task_get_data(task);
309aa9
+		while (slapi_task_get_refcount(task) > 0) {
309aa9
+			/* Yield to wait for the fixup task finishes. */
309aa9
+			DS_Sleep (PR_MillisecondsToInterval(100));
309aa9
+		}
309aa9
 		if (mydata) {
309aa9
 			slapi_ch_free_string(&mydata->dn);
309aa9
 			slapi_ch_free_string(&mydata->bind_dn);
309aa9
@@ -2803,6 +2818,8 @@ memberof_task_destructor(Slapi_Task *task)
309aa9
 			slapi_ch_free((void **)&mydata);
309aa9
 		}
309aa9
 	}
309aa9
+	slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
309aa9
+		"memberof_task_destructor <--\n" );
309aa9
 }
309aa9
 
309aa9
 int memberof_fix_memberof(MemberOfConfig *config, char *dn, char *filter_str)
309aa9
@@ -2841,6 +2858,13 @@ int memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data)
309aa9
 	memberof_del_dn_data del_data = {0, config->memberof_attr};
309aa9
 	Slapi_ValueSet *groups = 0;
309aa9
 
309aa9
+	/* 
309aa9
+	 * If the server is ordered to shutdown, stop the fixup and return an error.
309aa9
+	 */
309aa9
+	if (slapi_is_shutting_down()) {
309aa9
+		rc = -1;
309aa9
+		goto bail;
309aa9
+	}
309aa9
 	/* get a list of all of the groups this user belongs to */
309aa9
 	groups = memberof_get_groups(config, sdn);
309aa9
 
309aa9
@@ -2889,6 +2913,6 @@ int memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data)
309aa9
 	}
309aa9
 
309aa9
 	slapi_valueset_free(groups);
309aa9
-	
309aa9
+bail:
309aa9
 	return rc;
309aa9
 }
309aa9
diff --git a/ldap/servers/plugins/memberof/memberof.h b/ldap/servers/plugins/memberof/memberof.h
309aa9
index 6d56081..59029d7 100644
309aa9
--- a/ldap/servers/plugins/memberof/memberof.h
309aa9
+++ b/ldap/servers/plugins/memberof/memberof.h
309aa9
@@ -81,7 +81,7 @@ typedef struct memberofconfig {
309aa9
 	char *memberof_attr;
309aa9
 	int allBackends;
309aa9
 	Slapi_DN *entryScope;
309aa9
-        Slapi_DN *entryScopeExcludeSubtree;
309aa9
+	Slapi_DN *entryScopeExcludeSubtree;
309aa9
 	Slapi_Filter *group_filter;
309aa9
 	Slapi_Attr **group_slapiattrs;
309aa9
 } MemberOfConfig;
309aa9
diff --git a/ldap/servers/plugins/posix-winsync/posix-group-task.c b/ldap/servers/plugins/posix-winsync/posix-group-task.c
309aa9
index c5ea729..c76545a 100644
309aa9
--- a/ldap/servers/plugins/posix-winsync/posix-group-task.c
309aa9
+++ b/ldap/servers/plugins/posix-winsync/posix-group-task.c
309aa9
@@ -165,6 +165,10 @@ posix_group_task_destructor(Slapi_Task *task)
309aa9
 {
309aa9
     if (task) {
309aa9
         task_data *mydata = (task_data *) slapi_task_get_data(task);
309aa9
+        while (slapi_task_get_refcount(task) > 0) {
309aa9
+            /* Yield to wait for the fixup task finishes. */
309aa9
+            DS_Sleep (PR_MillisecondsToInterval(100));
309aa9
+        }
309aa9
         if (mydata) {
309aa9
             slapi_ch_free_string(&mydata->dn);
309aa9
             slapi_ch_free_string(&mydata->filter_str);
309aa9
@@ -172,6 +176,8 @@ posix_group_task_destructor(Slapi_Task *task)
309aa9
             slapi_ch_free((void **) &mydata);
309aa9
         }
309aa9
     }
309aa9
+    slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME,
309aa9
+                    "posix_group_task_destructor <--\n");
309aa9
 }
309aa9
 
309aa9
 #if 0 /* NOT USED */
309aa9
@@ -245,17 +251,28 @@ posix_group_fix_memberuid_callback(Slapi_Entry *e, void *callback_data)
309aa9
                     "_fix_memberuid ==>\n");
309aa9
     cb_data *the_cb_data = (cb_data *) callback_data;
309aa9
 
309aa9
-    int rc;
309aa9
+    int rc = 0;
309aa9
     Slapi_Attr *muid_attr = NULL;
309aa9
     Slapi_Value *v = NULL;
309aa9
 
309aa9
-    Slapi_Mods *smods = slapi_mods_new();
309aa9
-
309aa9
-    char *dn = slapi_entry_get_dn(e);
309aa9
-    Slapi_DN *sdn = slapi_entry_get_sdn(e);
309aa9
+    Slapi_Mods *smods = NULL;
309aa9
+    char *dn = NULL;
309aa9
+    Slapi_DN *sdn = NULL;
309aa9
     LDAPMod **mods = NULL;
309aa9
     int is_posix_group = 0;
309aa9
 
309aa9
+    /* 
309aa9
+     * If the server is ordered to shutdown, stop the fixup and return an error.
309aa9
+     */
309aa9
+    if (slapi_is_shutting_down()) {
309aa9
+        rc = -1;
309aa9
+        goto bail;
309aa9
+    }
309aa9
+
309aa9
+    smods = slapi_mods_new();
309aa9
+    dn = slapi_entry_get_dn(e);
309aa9
+    sdn = slapi_entry_get_sdn(e);
309aa9
+
309aa9
     if (hasObjectClass(e, "posixGroup")) {
309aa9
         is_posix_group = 1;
309aa9
     }
309aa9
@@ -441,7 +458,7 @@ posix_group_fix_memberuid_callback(Slapi_Entry *e, void *callback_data)
309aa9
         slapi_pblock_destroy(mod_pb);
309aa9
     }
309aa9
     slapi_mods_free(&smods);
309aa9
-
309aa9
+bail:
309aa9
     slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME,
309aa9
                     "_fix_memberuid <==\n");
309aa9
     /*
309aa9
@@ -450,7 +467,7 @@ posix_group_fix_memberuid_callback(Slapi_Entry *e, void *callback_data)
309aa9
      * uniqueMember attribute.  But "not found" error shoud not
309aa9
      * be returned, which stops the further fixup task.
309aa9
      */
309aa9
-    return 0;
309aa9
+    return rc;
309aa9
 }
309aa9
 
309aa9
 static void
309aa9
@@ -463,6 +480,12 @@ posix_group_fixup_task_thread(void *arg)
309aa9
     task_data *td = NULL;
309aa9
     int rc = 0;
309aa9
 
309aa9
+    if (!task) {
309aa9
+        return; /* no task */
309aa9
+    }
309aa9
+    slapi_task_inc_refcount(task);
309aa9
+    slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME,
309aa9
+                    "posix_group_fixup_task_thread --> refcount incremented.\n" );
309aa9
     /* Fetch our task data from the task */
309aa9
     td = (task_data *) slapi_task_get_data(task);
309aa9
 
309aa9
@@ -491,4 +514,7 @@ posix_group_fixup_task_thread(void *arg)
309aa9
 
309aa9
     slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME,
309aa9
                     "_task_thread <==\n");
309aa9
+    slapi_task_dec_refcount(task);
309aa9
+    slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME,
309aa9
+                    "posix_group_fixup_task_thread <-- refcount decremented.\n");
309aa9
 }
309aa9
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
309aa9
index 3bc3916..1570ba7 100644
309aa9
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
309aa9
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
309aa9
@@ -109,6 +109,8 @@ static CSN* replica_cleanallruv_find_maxcsn(Replica *replica, ReplicaId rid, cha
309aa9
 static int replica_cleanallruv_get_replica_maxcsn(Repl_Agmt *agmt, char *rid_text, char *basedn, CSN **csn);
309aa9
 static void preset_cleaned_rid(ReplicaId rid);
309aa9
 static multimaster_mtnode_extension * _replica_config_get_mtnode_ext (const Slapi_Entry *e);
309aa9
+static void replica_cleanall_ruv_destructor(Slapi_Task *task);
309aa9
+static void replica_cleanall_ruv_abort_destructor(Slapi_Task *task);
309aa9
 
309aa9
 /*
309aa9
  * Note: internal add/modify/delete operations should not be run while
309aa9
@@ -1509,6 +1511,10 @@ replica_cleanall_ruv_task(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
309aa9
         rc = SLAPI_DSE_CALLBACK_ERROR;
309aa9
         goto out;
309aa9
     }
309aa9
+
309aa9
+    /* register our destructor for waiting the task is done */
309aa9
+    slapi_task_set_destructor_fn(task, replica_cleanall_ruv_destructor);
309aa9
+
309aa9
     /*
309aa9
      *  Get our task settings
309aa9
      */
309aa9
@@ -1752,6 +1758,13 @@ replica_cleanallruv_thread(void *arg)
309aa9
     int aborted = 0;
309aa9
     int rc = 0;
309aa9
 
309aa9
+    if (!data) {
309aa9
+        return; /* no data */
309aa9
+    }
309aa9
+    if (data->task) {
309aa9
+        slapi_task_inc_refcount(data->task);
309aa9
+        slapi_log_error(SLAPI_LOG_PLUGIN, repl_plugin_name, "replica_cleanallruv_thread --> refcount incremented.\n");
309aa9
+    }
309aa9
     /*
309aa9
      *  Initialize our settings
309aa9
      */
309aa9
@@ -1974,6 +1987,8 @@ done:
309aa9
     }
309aa9
     if(data->task){
309aa9
         slapi_task_finish(data->task, rc);
309aa9
+        slapi_task_dec_refcount(data->task);
309aa9
+        slapi_log_error(SLAPI_LOG_PLUGIN, repl_plugin_name, "replica_cleanallruv_thread <-- refcount decremented.\n");
309aa9
     }
309aa9
     if(data->payload){
309aa9
         ber_bvfree(data->payload);
309aa9
@@ -1989,6 +2004,36 @@ done:
309aa9
     slapi_ch_free((void **)&data);
309aa9
 }
309aa9
 
309aa9
+static void
309aa9
+replica_cleanall_ruv_destructor(Slapi_Task *task)
309aa9
+{
309aa9
+	slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name,
309aa9
+		"replica_cleanall_ruv_destructor -->\n" );
309aa9
+	if (task) {
309aa9
+		while (slapi_task_get_refcount(task) > 0) {
309aa9
+			/* Yield to wait for the fixup task finishes. */
309aa9
+			DS_Sleep (PR_MillisecondsToInterval(100));
309aa9
+		}
309aa9
+	}
309aa9
+	slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name,
309aa9
+		"replica_cleanall_ruv_destructor <--\n" );
309aa9
+}
309aa9
+
309aa9
+static void
309aa9
+replica_cleanall_ruv_abort_destructor(Slapi_Task *task)
309aa9
+{
309aa9
+	slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name,
309aa9
+		"replica_cleanall_ruv_abort_destructor -->\n" );
309aa9
+	if (task) {
309aa9
+		while (slapi_task_get_refcount(task) > 0) {
309aa9
+			/* Yield to wait for the fixup task finishes. */
309aa9
+			DS_Sleep (PR_MillisecondsToInterval(100));
309aa9
+		}
309aa9
+	}
309aa9
+	slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name,
309aa9
+		"replica_cleanall_ruv_abort_destructor <--\n" );
309aa9
+}
309aa9
+
309aa9
 /*
309aa9
  *  Loop over the agmts, and check if they are in the last phase of cleaning, meaning they have
309aa9
  *  released cleanallruv data from the config
309aa9
@@ -2775,6 +2820,10 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter
309aa9
 
309aa9
     /* allocate new task now */
309aa9
     task = slapi_new_task(slapi_entry_get_ndn(e));
309aa9
+
309aa9
+    /* register our destructor for waiting the task is done */
309aa9
+    slapi_task_set_destructor_fn(task, replica_cleanall_ruv_abort_destructor);
309aa9
+
309aa9
     /*
309aa9
      *  Get our task settings
309aa9
      */
309aa9
@@ -2921,6 +2970,13 @@ replica_abort_task_thread(void *arg)
309aa9
     int release_it = 0;
309aa9
     int count = 0, rc = 0;
309aa9
 
309aa9
+    if (!data) {
309aa9
+        return; /* no data */
309aa9
+    }
309aa9
+    if (data->task) {
309aa9
+        slapi_task_inc_refcount(data->task);
309aa9
+        slapi_log_error(SLAPI_LOG_PLUGIN, repl_plugin_name, "replica_abort_task_thread --> refcount incremented.\n");
309aa9
+    }
309aa9
     cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Aborting task for rid(%d)...",data->rid);
309aa9
 
309aa9
     /*
309aa9
@@ -3028,6 +3084,8 @@ done:
309aa9
 
309aa9
     if(data->task){
309aa9
         slapi_task_finish(data->task, agmt_not_notified);
309aa9
+        slapi_task_dec_refcount(data->task);
309aa9
+        slapi_log_error(SLAPI_LOG_PLUGIN, repl_plugin_name, "replica_abort_task_thread <-- refcount incremented.\n");
309aa9
     }
309aa9
     if(data->repl_obj && release_it)
309aa9
         object_release(data->repl_obj);
309aa9
diff --git a/ldap/servers/plugins/schema_reload/schema_reload.c b/ldap/servers/plugins/schema_reload/schema_reload.c
309aa9
index b1a5bb8..25336fe 100644
309aa9
--- a/ldap/servers/plugins/schema_reload/schema_reload.c
309aa9
+++ b/ldap/servers/plugins/schema_reload/schema_reload.c
309aa9
@@ -86,6 +86,7 @@ static int schemareload_add(Slapi_PBlock *pb, Slapi_Entry *e,
309aa9
                     void *arg);
309aa9
 static int schemareload_start(Slapi_PBlock *pb);
309aa9
 static int schemareload_close(Slapi_PBlock *pb);
309aa9
+static void schemareload_destructor(Slapi_Task *task);
309aa9
 
309aa9
 /* 
309aa9
  * Init function
309aa9
@@ -159,6 +160,12 @@ schemareload_thread(void *arg)
309aa9
     int total_work = 2;
309aa9
     task_data *td = NULL;
309aa9
 
309aa9
+    if (!task) {
309aa9
+        return; /* no task */
309aa9
+    }
309aa9
+    slapi_task_inc_refcount(task);
309aa9
+    slapi_log_error(SLAPI_LOG_PLUGIN, "schemareload",
309aa9
+                    "schemareload_thread --> refcount incremented.\n" );
309aa9
     /* Fetch our task data from the task */
309aa9
     td = (task_data *)slapi_task_get_data(task);
309aa9
 
309aa9
@@ -174,7 +181,11 @@ schemareload_thread(void *arg)
309aa9
     rv = slapi_validate_schema_files(td->schemadir);
309aa9
     slapi_task_inc_progress(task);
309aa9
 
309aa9
-    if (LDAP_SUCCESS == rv) {
309aa9
+    if (slapi_is_shutting_down()) {
309aa9
+        slapi_task_log_notice(task, "Server is shuttoing down; Schema validation aborted.");
309aa9
+        slapi_task_log_status(task, "Server is shuttoing down; Schema validation aborted.");
309aa9
+        slapi_log_error(SLAPI_LOG_FATAL, "schemareload", "Server is shuttoing down; Schema validation aborted.");
309aa9
+    } else if (LDAP_SUCCESS == rv) {
309aa9
         slapi_task_log_notice(task, "Schema validation passed.");
309aa9
         slapi_task_log_status(task, "Schema validation passed.");
309aa9
         slapi_log_error(SLAPI_LOG_FATAL, "schemareload", "Schema validation passed.\n");
309aa9
@@ -199,16 +210,18 @@ schemareload_thread(void *arg)
309aa9
             slapi_task_log_status(task, "Schema reload task failed.");
309aa9
             slapi_log_error(SLAPI_LOG_FATAL, "schemareload", "Schema reload task failed.\n");
309aa9
         }
309aa9
-        PR_Unlock(schemareload_lock);
309aa9
     } else {
309aa9
         slapi_task_log_notice(task, "Schema validation failed.");
309aa9
         slapi_task_log_status(task, "Schema validation failed.");
309aa9
         slapi_log_error(SLAPI_LOG_FATAL, "schemareload", "Schema validation failed.\n");
309aa9
-        PR_Unlock(schemareload_lock);
309aa9
     }
309aa9
+    PR_Unlock(schemareload_lock);
309aa9
 
309aa9
     /* this will queue the destruction of the task */
309aa9
     slapi_task_finish(task, rv);
309aa9
+    slapi_task_dec_refcount(task);
309aa9
+    slapi_log_error(SLAPI_LOG_PLUGIN, "schemareload",
309aa9
+                    "schemareload_thread <-- refcount decremented.\n");
309aa9
 }
309aa9
 
309aa9
 /* extract a single value from the entry (as a string) -- if it's not in the
309aa9
@@ -233,6 +246,10 @@ schemareload_destructor(Slapi_Task *task)
309aa9
 {
309aa9
     if (task) {
309aa9
         task_data *mydata = (task_data *)slapi_task_get_data(task);
309aa9
+        while (slapi_task_get_refcount(task) > 0) {
309aa9
+            /* Yield to wait for the fixup task finishes. */
309aa9
+            DS_Sleep (PR_MillisecondsToInterval(100));
309aa9
+        }
309aa9
         if (mydata) {
309aa9
             slapi_ch_free_string(&mydata->schemadir);
309aa9
             slapi_ch_free_string(&mydata->bind_dn);
309aa9
diff --git a/ldap/servers/plugins/syntaxes/validate_task.c b/ldap/servers/plugins/syntaxes/validate_task.c
309aa9
index 99f6309..71b4b7e 100644
309aa9
--- a/ldap/servers/plugins/syntaxes/validate_task.c
309aa9
+++ b/ldap/servers/plugins/syntaxes/validate_task.c
309aa9
@@ -179,6 +179,10 @@ syntax_validate_task_destructor(Slapi_Task *task)
309aa9
 {
309aa9
 	if (task) {
309aa9
 		task_data *mydata = (task_data *)slapi_task_get_data(task);
309aa9
+		while (slapi_task_get_refcount(task) > 0) {
309aa9
+			/* Yield to wait for the fixup task finishes. */
309aa9
+			DS_Sleep (PR_MillisecondsToInterval(100));
309aa9
+		}
309aa9
 		if (mydata) {
309aa9
 			slapi_ch_free_string(&mydata->dn);
309aa9
 			slapi_ch_free_string(&mydata->filter_str);
309aa9
@@ -197,6 +201,12 @@ syntax_validate_task_thread(void *arg)
309aa9
 	task_data *td = NULL;
309aa9
 	Slapi_PBlock *search_pb = slapi_pblock_new();
309aa9
 
309aa9
+	if (!task) {
309aa9
+		return; /* no task */
309aa9
+	}
309aa9
+	slapi_task_inc_refcount(task);
309aa9
+	slapi_log_error(SLAPI_LOG_PLUGIN, SYNTAX_PLUGIN_SUBSYSTEM,
309aa9
+	                "syntax_validate_task_thread --> refcount incremented.\n" );
309aa9
 	/* Fetch our task data from the task */
309aa9
 	td = (task_data *)slapi_task_get_data(task);
309aa9
 
309aa9
@@ -231,16 +241,26 @@ syntax_validate_task_thread(void *arg)
309aa9
 
309aa9
 	/* this will queue the destruction of the task */
309aa9
 	slapi_task_finish(task, rc);
309aa9
+	slapi_task_dec_refcount(task);
309aa9
+	slapi_log_error(SLAPI_LOG_PLUGIN, SYNTAX_PLUGIN_SUBSYSTEM,
309aa9
+	                "syntax_validate_task_thread <-- refcount decremented.\n"); 
309aa9
 }
309aa9
 
309aa9
 static int
309aa9
 syntax_validate_task_callback(Slapi_Entry *e, void *callback_data)
309aa9
 {
309aa9
-        int rc = 0;
309aa9
-        char *dn = slapi_entry_get_dn(e);
309aa9
+	int rc = 0;
309aa9
+	char *dn = slapi_entry_get_dn(e);
309aa9
 	task_data *td = (task_data *)callback_data;
309aa9
 	Slapi_PBlock *pb = NULL;
309aa9
 
309aa9
+	/* 
309aa9
+	 * If the server is ordered to shutdown, stop the fixup and return an error.
309aa9
+	 */
309aa9
+	if (slapi_is_shutting_down()) {
309aa9
+		rc = -1;
309aa9
+		goto bail;
309aa9
+	}
309aa9
 	/* Override the syntax checking config to force syntax checking. */
309aa9
 	if (slapi_entry_syntax_check(NULL, e, 1) != 0) {
309aa9
 		char *error_text = NULL;
309aa9
@@ -261,7 +281,7 @@ syntax_validate_task_callback(Slapi_Entry *e, void *callback_data)
309aa9
 		/* Keep a tally of the number of invalid entries found. */
309aa9
 		slapi_counter_increment(td->invalid_entries);
309aa9
 	}
309aa9
-
309aa9
+bail:
309aa9
 	return rc;
309aa9
 }
309aa9
 
309aa9
diff --git a/ldap/servers/plugins/usn/usn_cleanup.c b/ldap/servers/plugins/usn/usn_cleanup.c
309aa9
index c12dfd2..dd07b4c 100644
309aa9
--- a/ldap/servers/plugins/usn/usn_cleanup.c
309aa9
+++ b/ldap/servers/plugins/usn/usn_cleanup.c
309aa9
@@ -49,6 +49,8 @@ struct usn_cleanup_data {
309aa9
 
309aa9
 static int usn_cleanup_add(Slapi_PBlock *pb, Slapi_Entry *e,
309aa9
             Slapi_Entry *eAfter, int *returncode, char *returntext, void *arg);
309aa9
+static void usn_cleanup_task_destructor(Slapi_Task *task);
309aa9
+
309aa9
 
309aa9
 int
309aa9
 usn_cleanup_start(Slapi_PBlock *pb)
309aa9
@@ -83,8 +85,14 @@ usn_cleanup_thread(void *arg)
309aa9
     Slapi_PBlock *delete_pb = NULL;
309aa9
     char *filter = "objectclass=nsTombstone";
309aa9
 
309aa9
+	if (!task) {
309aa9
+		return; /* no task */
309aa9
+	}
309aa9
     slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
309aa9
                     "--> usn_cleanup_thread\n");
309aa9
+	slapi_task_inc_refcount(task);
309aa9
+	slapi_log_error(SLAPI_LOG_PLUGIN, USN_PLUGIN_SUBSYSTEM,
309aa9
+	                "usn_cleanup_thread --> refcount incremented.\n" );
309aa9
 
309aa9
     if (NULL == usn_get_identity()) { /* plugin is not initialized */
309aa9
         slapi_task_log_notice(task, "USN plugin is not initialized\n");
309aa9
@@ -195,14 +203,12 @@ bail:
309aa9
     if (cleanup_data->maxusn_to_delete) {
309aa9
         slapi_ch_free_string(&filter);
309aa9
     }
309aa9
-    slapi_ch_free_string(&cleanup_data->maxusn_to_delete);
309aa9
-    slapi_ch_free_string(&cleanup_data->suffix);
309aa9
-    slapi_ch_free_string(&cleanup_data->bind_dn);
309aa9
-    slapi_ch_free((void **)&cleanup_data);
309aa9
 
309aa9
     /* this will queue the destruction of the task */
309aa9
     slapi_task_finish(task, rv);
309aa9
-
309aa9
+	slapi_task_dec_refcount(task);
309aa9
+	slapi_log_error(SLAPI_LOG_PLUGIN, USN_PLUGIN_SUBSYSTEM,
309aa9
+	                "usn_cleanup_thread <-- refcount decremented.\n");
309aa9
     slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
309aa9
                     "<-- usn_cleanup_thread\n");
309aa9
 }
309aa9
@@ -283,7 +289,7 @@ usn_cleanup_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
309aa9
     backend = slapi_entry_attr_get_charptr(e, "backend");
309aa9
     maxusn = slapi_entry_attr_get_charptr(e, "maxusn_to_delete");
309aa9
 
309aa9
-    if (NULL == suffix && NULL == backend) {
309aa9
+    if (!suffix && !backend) {
309aa9
         slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
309aa9
             "USN tombstone cleanup: Both suffix and backend are missing.\n");
309aa9
         *returncode = LDAP_PARAM_ERROR;
309aa9
@@ -292,7 +298,7 @@ usn_cleanup_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
309aa9
     }
309aa9
 
309aa9
     /* suffix is not given, but backend is; get the suffix */
309aa9
-    if (NULL == suffix && NULL != backend) {
309aa9
+    if (!suffix && backend) {
309aa9
         be = slapi_be_select_by_instance_name(backend);
309aa9
         be_suffix = slapi_be_getsuffix(be, 0);
309aa9
         if (be_suffix) {
309aa9
@@ -317,12 +323,6 @@ usn_cleanup_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
309aa9
         goto bail;
309aa9
     }
309aa9
 
309aa9
-    cleanup_data =
309aa9
-      (struct usn_cleanup_data *)slapi_ch_malloc(sizeof(struct usn_cleanup_data));
309aa9
-    cleanup_data->suffix = slapi_ch_strdup(suffix);
309aa9
-    cleanup_data->maxusn_to_delete = slapi_ch_strdup(maxusn);
309aa9
-    cleanup_data->bind_dn = slapi_ch_strdup(bind_dn);
309aa9
-
309aa9
     /* allocate new task now */
309aa9
     task = slapi_plugin_new_task(slapi_entry_get_ndn(e), arg);
309aa9
     if (task == NULL) {
309aa9
@@ -330,11 +330,21 @@ usn_cleanup_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
309aa9
             "USN tombstone cleanup: unable to allocate new task.\n");
309aa9
         *returncode = LDAP_OPERATIONS_ERROR;
309aa9
         rv = SLAPI_DSE_CALLBACK_ERROR;
309aa9
-        slapi_ch_free((void**)&cleanup_data);
309aa9
         goto bail;
309aa9
     }
309aa9
 
309aa9
+    /* register our destructor for cleaning up our private data */
309aa9
+    slapi_task_set_destructor_fn(task, usn_cleanup_task_destructor);
309aa9
+
309aa9
     /* Stash our argument in the task for use by the task thread */
309aa9
+    cleanup_data =
309aa9
+      (struct usn_cleanup_data *)slapi_ch_malloc(sizeof(struct usn_cleanup_data));
309aa9
+    cleanup_data->suffix = suffix;
309aa9
+	suffix = NULL; /* don't free in this function */
309aa9
+    cleanup_data->maxusn_to_delete = maxusn;
309aa9
+	maxusn = NULL; /* don't free in this function */
309aa9
+    cleanup_data->bind_dn = bind_dn;
309aa9
+    bind_dn = NULL; /* don't free in this function */
309aa9
     slapi_task_set_data(task, cleanup_data);
309aa9
 
309aa9
     /* start the USN tombstone cleanup task as a separate thread */
309aa9
@@ -361,3 +371,23 @@ bail:
309aa9
     return rv;
309aa9
 }
309aa9
 
309aa9
+static void
309aa9
+usn_cleanup_task_destructor(Slapi_Task *task)
309aa9
+{
309aa9
+    slapi_log_error(SLAPI_LOG_PLUGIN, USN_PLUGIN_SUBSYSTEM, "usn_cleanup_task_destructor -->\n");
309aa9
+    if (task) {
309aa9
+        struct usn_cleanup_data *mydata = (struct usn_cleanup_data *)slapi_task_get_data(task);
309aa9
+        while (slapi_task_get_refcount(task) > 0) {
309aa9
+            /* Yield to wait for the fixup task finishes. */
309aa9
+            DS_Sleep (PR_MillisecondsToInterval(100));
309aa9
+        }
309aa9
+        if (mydata) {
309aa9
+            slapi_ch_free_string(&mydata->suffix);
309aa9
+            slapi_ch_free_string(&mydata->maxusn_to_delete);
309aa9
+            slapi_ch_free_string(&mydata->bind_dn);
309aa9
+            /* Need to cast to avoid a compiler warning */
309aa9
+            slapi_ch_free((void **)&mydata);
309aa9
+        }
309aa9
+    }
309aa9
+    slapi_log_error(SLAPI_LOG_PLUGIN, USN_PLUGIN_SUBSYSTEM, "usn_cleanup_task_destructor <--\n");
309aa9
+}
309aa9
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
309aa9
index 0ae3601..dfe75eb 100644
309aa9
--- a/ldap/servers/slapd/slapi-plugin.h
309aa9
+++ b/ldap/servers/slapd/slapi-plugin.h
309aa9
@@ -7958,6 +7958,15 @@ void slapi_plugin_op_finished(void *arg);
309aa9
 #define RDN_IS_CONFLICT  0x2
309aa9
 int slapi_is_special_rdn(const char *rdn, int flag);
309aa9
 
309aa9
+/**
309aa9
+ * Sleeps for PRIntervalTime ticks defined in NSPR library
309aa9
+ *
309aa9
+ * \param PRIntervalTime ticks
309aa9
+ *
309aa9
+ * \return Nothing
309aa9
+ */
309aa9
+void    DS_Sleep(PRIntervalTime ticks);
309aa9
+
309aa9
 #ifdef __cplusplus
309aa9
 }
309aa9
 #endif
309aa9
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
309aa9
index 921c397..9ca1950 100644
309aa9
--- a/ldap/servers/slapd/slapi-private.h
309aa9
+++ b/ldap/servers/slapd/slapi-private.h
309aa9
@@ -1245,8 +1245,6 @@ void bervalarray_add_berval_fast(struct berval ***vals, const struct berval *add
309aa9
 
309aa9
 /***** End of items added for the replication plugin. ***********************/
309aa9
 
309aa9
-void    DS_Sleep(PRIntervalTime ticks);
309aa9
-
309aa9
 /* macro to specify the behavior of upgradedb & upgradednformat */
309aa9
 #define SLAPI_UPGRADEDB_FORCE    0x1  /* reindex all (no check w/ idl switch) */
309aa9
 #define SLAPI_UPGRADEDB_SKIPINIT 0x2  /* call upgradedb as part of other op */
309aa9
diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
309aa9
index 98ec88c..19a52a3 100644
309aa9
--- a/ldap/servers/slapd/task.c
309aa9
+++ b/ldap/servers/slapd/task.c
309aa9
@@ -113,6 +113,8 @@ static const char *fetch_attr(Slapi_Entry *e, const char *attrname,
309aa9
 static Slapi_Entry *get_internal_entry(Slapi_PBlock *pb, char *dn);
309aa9
 static void modify_internal_entry(char *dn, LDAPMod **mods);
309aa9
 
309aa9
+static void fixup_tombstone_task_destructor(Slapi_Task *task);
309aa9
+
309aa9
 /***********************************
309aa9
  * Public Functions
309aa9
  ***********************************/ 
309aa9
@@ -2218,6 +2220,12 @@ task_fixup_tombstone_thread(void *arg)
309aa9
     int fixup_count = 0;
309aa9
     int rc, i, j;
309aa9
 
309aa9
+    if (!task) {
309aa9
+        return; /* no task */
309aa9
+    }
309aa9
+    slapi_task_inc_refcount(task);
309aa9
+    slapi_log_error(SLAPI_LOG_PLUGIN, TASK_TOMBSTONE_FIXUP,
309aa9
+                    "fixup_tombstone_task_thread --> refcount incremented.\n" );
309aa9
     slapi_task_begin(task, 1);
309aa9
     slapi_task_log_notice(task, "Beginning tombstone fixup task...\n");
309aa9
     slapi_log_error(SLAPI_LOG_REPL, TASK_TOMBSTONE_FIXUP,
309aa9
@@ -2233,8 +2241,14 @@ task_fixup_tombstone_thread(void *arg)
309aa9
 
309aa9
     /* Okay check the specified backends only */
309aa9
     for(i = 0; base && base[i]; i++){
309aa9
-        Slapi_PBlock *search_pb = slapi_pblock_new();
309aa9
+        Slapi_PBlock *search_pb = NULL;
309aa9
+
309aa9
+        if (slapi_is_shutting_down()) {
309aa9
+            rc = -1;
309aa9
+            goto bail;
309aa9
+        }
309aa9
 
309aa9
+        search_pb = slapi_pblock_new();
309aa9
         /* find entries that need fixing... */
309aa9
         slapi_search_internal_set_pb(search_pb, base[i], LDAP_SCOPE_SUBTREE,
309aa9
                 filter, NULL, 0, NULL, NULL, plugin_get_default_component_id(), 0);
309aa9
@@ -2247,8 +2261,7 @@ task_fixup_tombstone_thread(void *arg)
309aa9
             slapi_log_error(SLAPI_LOG_REPL, TASK_TOMBSTONE_FIXUP,
309aa9
                     "Failed to search backend for tombstones, error %d\n", rc);
309aa9
             slapi_pblock_destroy(search_pb);
309aa9
-            slapi_task_finish(task, rc);
309aa9
-            return;
309aa9
+            goto bail;
309aa9
         }
309aa9
 
309aa9
         slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
309aa9
@@ -2281,9 +2294,11 @@ task_fixup_tombstone_thread(void *arg)
309aa9
     slapi_log_error(SLAPI_LOG_REPL, TASK_TOMBSTONE_FIXUP, "%s %d tombstones.\n",
309aa9
                     task_data->stripcsn ? "Stripped" : "Fixed", fixup_count);
309aa9
     slapi_task_inc_progress(task);
309aa9
+bail:
309aa9
     slapi_task_finish(task, rc);
309aa9
-    slapi_ch_array_free(base);
309aa9
-    slapi_ch_free((void **)&task_data);
309aa9
+    slapi_task_dec_refcount(task);
309aa9
+    slapi_log_error(SLAPI_LOG_PLUGIN, TASK_TOMBSTONE_FIXUP,
309aa9
+                    "fixup_tombstone_task_thread <-- refcount decremented.\n" );
309aa9
 }
309aa9
 
309aa9
 
309aa9
@@ -2387,6 +2402,8 @@ task_fixup_tombstones_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
309aa9
     }
309aa9
 
309aa9
     task = slapi_new_task(slapi_entry_get_ndn(e));
309aa9
+    /* register our destructor for cleaning up our private data */
309aa9
+    slapi_task_set_destructor_fn(task, fixup_tombstone_task_destructor);
309aa9
     task_data = (struct task_tombstone_data *)slapi_ch_calloc(1, sizeof(struct task_tombstone_data));
309aa9
     task_data->base = base;
309aa9
     task_data->task = task;
309aa9
@@ -2422,6 +2439,26 @@ done:
309aa9
     return SLAPI_DSE_CALLBACK_OK;
309aa9
 }
309aa9
 
309aa9
+static void
309aa9
+fixup_tombstone_task_destructor(Slapi_Task *task)
309aa9
+{
309aa9
+    slapi_log_error(SLAPI_LOG_PLUGIN, TASK_TOMBSTONE_FIXUP,
309aa9
+                    "fixup_tombstone_task_destructor -->\n" );
309aa9
+    if (task) {
309aa9
+        struct task_tombstone_data *mydata = (struct task_tombstone_data *)slapi_task_get_data(task);
309aa9
+        while (slapi_task_get_refcount(task) > 0) {
309aa9
+            /* Yield to wait for the fixup task finishes. */
309aa9
+            DS_Sleep (PR_MillisecondsToInterval(100));
309aa9
+        }
309aa9
+        if (mydata) {
309aa9
+            slapi_ch_array_free(mydata->base);
309aa9
+            slapi_ch_free((void **)&mydata);
309aa9
+        }
309aa9
+    }
309aa9
+    slapi_log_error(SLAPI_LOG_PLUGIN, TASK_TOMBSTONE_FIXUP,
309aa9
+                    "fixup_tombstone_task_destructor <--\n" );
309aa9
+}
309aa9
+
309aa9
 /* cleanup old tasks that may still be in the DSE from a previous session
309aa9
  * (this can happen if the server crashes [no matter how unlikely we like
309aa9
  * to think that is].)
309aa9
-- 
309aa9
1.9.3
309aa9