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

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