diff --git a/SOURCES/0061-Ticket-48005-ns-slapd-crash-in-shutdown-phase.patch b/SOURCES/0061-Ticket-48005-ns-slapd-crash-in-shutdown-phase.patch
new file mode 100644
index 0000000..3d59efe
--- /dev/null
+++ b/SOURCES/0061-Ticket-48005-ns-slapd-crash-in-shutdown-phase.patch
@@ -0,0 +1,1057 @@
+From 2e87dafa9d39e6ab08382612be762c25afa80d4f Mon Sep 17 00:00:00 2001
+From: Noriko Hosoi <nhosoi@redhat.com>
+Date: Sun, 15 Feb 2015 17:34:12 -0800
+Subject: [PATCH] Ticket #48005 - ns-slapd crash in shutdown phase
+
+Description: There was a small window that long running tasks access its
+own task object after it's aready released by main thread in the shutdown
+period.  This patch adds refcounter to such threads and make destructor
+wait until the counter becomes 0.  Plus, the shutdown check is added to
+their task callbacks.
+
+Following tasks are updated by this patch:
+  slapd/task.c:                         "fixup tombstones"
+  posix-winsync/posix-winsync-config.c: "memberuid task"
+  replication/repl5_replica_config.c:   "cleanallruv"
+  replication/repl5_replica_config.c:   "abort cleanallruv"
+  syntaxes/validate_task.c:             "syntax validate"
+  automember/automember.c:              "automember rebuild membership"
+  automember/automember.c:              "automember export updates"
+  automember/automember.c:              "automember map updates"
+  linkedattrs/linked_attrs.c:           "fixup linked attributes"
+  memberof/memberof.c:                  "memberof task"
+  schema_reload/schema_reload.c:        "schema reload task"
+  usn/usn_cleanup.c:                    "USN tombstone cleanup task"
+
+Following tasks are already covered:
+  slapd/task.c: "import"
+  slapd/task.c: "index"
+  slapd/task.c: "upgradedb"
+
+Following tasks are processed in an ordinary worker thread; no need to change
+  slapd/task.c: "sysconfig reload"
+  slapd/task.c: "export"
+  slapd/task.c: "backup"
+  slapd/task.c: "restore"
+
+(cherry picked from commit ab2e26de21beb5a92d2a18ab5a20db9637b83c7a)
+(cherry picked from commit eebbabbaba8f024671158f527a169fc378ff01d6)
+
+Conflicts:
+	ldap/servers/plugins/memberof/memberof.c
+---
+ ldap/servers/plugins/automember/automember.c       | 70 ++++++++++++++++++----
+ ldap/servers/plugins/linkedattrs/fixup_task.c      | 40 +++++++++++--
+ ldap/servers/plugins/memberof/memberof.c           | 26 +++++++-
+ ldap/servers/plugins/memberof/memberof.h           |  2 +-
+ .../plugins/posix-winsync/posix-group-task.c       | 40 ++++++++++---
+ .../plugins/replication/repl5_replica_config.c     | 58 ++++++++++++++++++
+ ldap/servers/plugins/schema_reload/schema_reload.c | 23 ++++++-
+ ldap/servers/plugins/syntaxes/validate_task.c      | 26 +++++++-
+ ldap/servers/plugins/usn/usn_cleanup.c             | 58 +++++++++++++-----
+ ldap/servers/slapd/slapi-plugin.h                  |  9 +++
+ ldap/servers/slapd/slapi-private.h                 |  2 -
+ ldap/servers/slapd/task.c                          | 47 +++++++++++++--
+ 12 files changed, 348 insertions(+), 53 deletions(-)
+
+diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c
+index 6a8fd22..b2914db 100644
+--- a/ldap/servers/plugins/automember/automember.c
++++ b/ldap/servers/plugins/automember/automember.c
+@@ -119,9 +119,9 @@ static int automember_task_add_map_entries(Slapi_PBlock *pb, Slapi_Entry *e, Sla
+ void automember_rebuild_task_thread(void *arg);
+ void automember_export_task_thread(void *arg);
+ void automember_map_task_thread(void *arg);
+-void automember_task_destructor(Slapi_Task *task);
+-void automember_task_export_destructor(Slapi_Task *task);
+-void automember_task_map_destructor(Slapi_Task *task);
++static void automember_task_destructor(Slapi_Task *task);
++static void automember_task_export_destructor(Slapi_Task *task);
++static void automember_task_map_destructor(Slapi_Task *task);
+ 
+ #define DEFAULT_FILE_MODE PR_IRUSR | PR_IWUSR
+ 
+@@ -1962,11 +1962,15 @@ fetch_attr(Slapi_Entry *e, const char *attrname, const char *default_val)
+     return slapi_value_get_string(val);
+ }
+ 
+-void
++static void
+ automember_task_destructor(Slapi_Task *task)
+ {
+     if (task) {
+         task_data *mydata = (task_data *)slapi_task_get_data(task);
++		while (slapi_task_get_refcount(task) > 0) {
++			/* Yield to wait for the fixup task finishes. */
++			DS_Sleep (PR_MillisecondsToInterval(100));
++		}
+         if (mydata) {
+             slapi_ch_free_string(&mydata->bind_dn);
+             slapi_sdn_free(&mydata->base_dn);
+@@ -1976,11 +1980,15 @@ automember_task_destructor(Slapi_Task *task)
+     }
+ }
+ 
+-void
++static void
+ automember_task_export_destructor(Slapi_Task *task)
+ {
+     if (task) {
+         task_data *mydata = (task_data *)slapi_task_get_data(task);
++		while (slapi_task_get_refcount(task) > 0) {
++			/* Yield to wait for the fixup task finishes. */
++			DS_Sleep (PR_MillisecondsToInterval(100));
++		}
+         if (mydata) {
+             slapi_ch_free_string(&mydata->ldif_out);
+             slapi_ch_free_string(&mydata->bind_dn);
+@@ -1991,11 +1999,15 @@ automember_task_export_destructor(Slapi_Task *task)
+     }
+ }
+ 
+-void
++static void
+ automember_task_map_destructor(Slapi_Task *task)
+ {
+     if (task) {
+         task_data *mydata = (task_data *)slapi_task_get_data(task);
++		while (slapi_task_get_refcount(task) > 0) {
++			/* Yield to wait for the fixup task finishes. */
++			DS_Sleep (PR_MillisecondsToInterval(100));
++		}
+         if (mydata) {
+             slapi_ch_free_string(&mydata->ldif_out);
+             slapi_ch_free_string(&mydata->ldif_in);
+@@ -2114,7 +2126,8 @@ out:
+  *  Search using the basedn, filter, and scope provided from the task data.
+  *  Then loop of each entry, and apply the membership if applicable.
+  */
+-void automember_rebuild_task_thread(void *arg){
++void automember_rebuild_task_thread(void *arg)
++{
+     Slapi_Task *task = (Slapi_Task *)arg;
+     struct configEntry *config = NULL;
+     Slapi_PBlock *search_pb = NULL, *fixup_pb = NULL;
+@@ -2124,6 +2137,12 @@ void automember_rebuild_task_thread(void *arg){
+     int result = 0;
+     int i = 0;
+ 
++    if (!task) {
++        return; /* no task */
++    }
++    slapi_task_inc_refcount(task);
++    slapi_log_error( SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
++                     "automember_rebuild_task_thread --> refcount incremented.\n" );
+     /*
+      *  Fetch our task data from the task
+      */
+@@ -2192,7 +2211,8 @@ void automember_rebuild_task_thread(void *arg){
+                 if (slapi_dn_issuffix(slapi_entry_get_dn(entries[i]), config->scope) &&
+                     (slapi_filter_test_simple(entries[i], config->filter) == 0))
+                 {
+-                    if(automember_update_membership(config, entries[i], NULL)){
++                    if (slapi_is_shutting_down() ||
++                        automember_update_membership(config, entries[i], NULL)) {
+                         result = SLAPI_PLUGIN_FAILURE;
+                         automember_config_unlock();
+                         goto out;
+@@ -2226,6 +2246,9 @@ out:
+     }
+     slapi_task_inc_progress(task);
+     slapi_task_finish(task, result);
++    slapi_task_dec_refcount(task);
++    slapi_log_error( SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
++                     "automember_rebuild_task_thread <-- refcount decremented.\n" );
+ }
+ 
+ /*
+@@ -2328,7 +2351,8 @@ out:
+     return rv;
+ }
+ 
+-void automember_export_task_thread(void *arg){
++void automember_export_task_thread(void *arg)
++{
+     Slapi_Task *task = (Slapi_Task *)arg;
+     Slapi_PBlock *search_pb = NULL;
+     Slapi_Entry **entries = NULL;
+@@ -2340,6 +2364,13 @@ void automember_export_task_thread(void *arg){
+     int i = 0;
+     int rc = 0;
+ 
++    if (!task) {
++        return; /* no task */
++    }
++    slapi_task_inc_refcount(task);
++    slapi_log_error( SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
++                     "automember_export_task_thread --> refcount incremented.\n" );
++
+     td = (task_data *)slapi_task_get_data(task);
+     slapi_task_begin(task, 1);
+     slapi_task_log_notice(task, "Automember export task starting.  Exporting changes to (%s)", td->ldif_out);
+@@ -2394,7 +2425,8 @@ void automember_export_task_thread(void *arg){
+                 if (slapi_dn_issuffix(slapi_sdn_get_dn(td->base_dn), config->scope) &&
+                     (slapi_filter_test_simple(entries[i], config->filter) == 0))
+                 { 
+-                    if(automember_update_membership(config, entries[i], ldif_fd)){
++                    if (slapi_is_shutting_down() ||
++                        automember_update_membership(config, entries[i], ldif_fd)) {
+                         result = SLAPI_DSE_CALLBACK_ERROR;
+                         automember_config_unlock();
+                         goto out;
+@@ -2423,6 +2455,9 @@ out:
+     }
+     slapi_task_inc_progress(task);
+     slapi_task_finish(task, result);
++    slapi_task_dec_refcount(task);
++    slapi_log_error( SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
++                     "automember_export_task_thread <-- refcount decremented.\n" );
+ }
+ 
+ /*
+@@ -2507,7 +2542,8 @@ out:
+  *  Read in the text entries from ldif_in, and convert them to slapi_entries.
+  *  Then, write to ldif_out what the updates would be if these entries were added
+  */
+-void automember_map_task_thread(void *arg){
++void automember_map_task_thread(void *arg)
++{
+     Slapi_Task *task = (Slapi_Task *)arg;
+     Slapi_Entry *e = NULL;
+     int result = SLAPI_DSE_CALLBACK_OK;
+@@ -2527,6 +2563,12 @@ void automember_map_task_thread(void *arg){
+ #endif
+     int rc = 0;
+ 
++    if (!task) {
++        return; /* no task */
++    }
++    slapi_task_inc_refcount(task);
++    slapi_log_error( SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
++                     "automember_map_task_thread --> refcount incremented.\n" );
+     td = (task_data *)slapi_task_get_data(task);
+     slapi_task_begin(task, 1);
+     slapi_task_log_notice(task, "Automember map task starting...  Reading entries from (%s)"
+@@ -2586,7 +2628,8 @@ void automember_map_task_thread(void *arg){
+                     if (slapi_dn_issuffix(slapi_entry_get_dn_const(e), config->scope) &&
+                         (slapi_filter_test_simple(e, config->filter) == 0))
+                     {
+-                        if(automember_update_membership(config, e, ldif_fd_out)){
++                        if (slapi_is_shutting_down() ||
++                            automember_update_membership(config, e, ldif_fd_out)) {
+                             result = SLAPI_DSE_CALLBACK_ERROR;
+                             slapi_entry_free(e);
+                             slapi_ch_free_string(&entrystr);
+@@ -2620,6 +2663,9 @@ out:
+     }
+     slapi_task_inc_progress(task);
+     slapi_task_finish(task, result);
++    slapi_task_dec_refcount(task);
++    slapi_log_error( SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
++                     "automember_map_task_thread <-- refcount decremented.\n" );
+ }
+ 
+ /*
+diff --git a/ldap/servers/plugins/linkedattrs/fixup_task.c b/ldap/servers/plugins/linkedattrs/fixup_task.c
+index db3c693..3a01fed 100644
+--- a/ldap/servers/plugins/linkedattrs/fixup_task.c
++++ b/ldap/servers/plugins/linkedattrs/fixup_task.c
+@@ -119,6 +119,10 @@ linked_attrs_fixup_task_destructor(Slapi_Task *task)
+ {
+ 	if (task) {
+ 		task_data *mydata = (task_data *)slapi_task_get_data(task);
++		while (slapi_task_get_refcount(task) > 0) {
++			/* Yield to wait for the fixup task finishes. */
++			DS_Sleep (PR_MillisecondsToInterval(100));
++		}
+ 		if (mydata) {
+ 			slapi_ch_free_string(&mydata->linkdn);
+ 			slapi_ch_free_string(&mydata->bind_dn);
+@@ -137,6 +141,12 @@ linked_attrs_fixup_task_thread(void *arg)
+ 	int found_config = 0;
+ 	int rc = 0;
+ 
++	if (!task) {
++		return; /* no task */
++	}
++	slapi_task_inc_refcount(task);
++	slapi_log_error(SLAPI_LOG_PLUGIN, LINK_PLUGIN_SUBSYSTEM,
++	                "linked_attrs_fixup_task_thread --> refcount incremented.\n" );
+ 	/* Fetch our task data from the task */
+ 	td = (task_data *)slapi_task_get_data(task);
+ 
+@@ -154,8 +164,8 @@ linked_attrs_fixup_task_thread(void *arg)
+     linked_attrs_read_lock();
+     main_config = linked_attrs_get_config();
+     if (!PR_CLIST_IS_EMPTY(main_config)) {
+-       struct configEntry *config_entry = NULL;
+-       PRCList *list = PR_LIST_HEAD(main_config);
++        struct configEntry *config_entry = NULL;
++        PRCList *list = PR_LIST_HEAD(main_config);
+ 
+         while (list != main_config) {
+             config_entry = (struct configEntry *) list;
+@@ -204,6 +214,10 @@ linked_attrs_fixup_task_thread(void *arg)
+ 
+ 	/* this will queue the destruction of the task */
+ 	slapi_task_finish(task, rc);
++
++	slapi_task_dec_refcount(task);
++	slapi_log_error(SLAPI_LOG_PLUGIN, LINK_PLUGIN_SUBSYSTEM,
++	                "linked_attrs_fixup_task_thread <-- refcount decremented.\n");
+ }
+ 
+ static void 
+@@ -269,7 +283,7 @@ linked_attrs_fixup_links(struct configEntry *config)
+             if(rc == 0){
+                 slapi_back_transaction_commit(fixup_pb);
+             } else {
+-            	slapi_back_transaction_abort(fixup_pb);
++                slapi_back_transaction_abort(fixup_pb);
+             }
+             slapi_pblock_destroy(fixup_pb);
+         }
+@@ -352,11 +366,20 @@ linked_attrs_remove_backlinks_callback(Slapi_Entry *e, void *callback_data)
+     int rc = 0;
+     Slapi_DN *sdn = slapi_entry_get_sdn(e);
+     char *type = (char *)callback_data;
+-    Slapi_PBlock *pb = slapi_pblock_new();
++    Slapi_PBlock *pb = NULL;
+     char *val[1];
+     LDAPMod mod;
+     LDAPMod *mods[2];
+ 
++    /* 
++     * If the server is ordered to shutdown, stop the fixup and return an error.
++     */
++    if (slapi_is_shutting_down()) {
++        rc = -1;
++        goto bail;
++    }
++
++    pb = slapi_pblock_new();
+     /* Remove all values of the passed in type. */
+     val[0] = 0;
+ 
+@@ -377,7 +400,7 @@ linked_attrs_remove_backlinks_callback(Slapi_Entry *e, void *callback_data)
+     slapi_modify_internal_pb(pb);
+ 
+     slapi_pblock_destroy(pb);
+-
++bail:
+     return rc;
+ }
+ 
+@@ -394,6 +417,13 @@ linked_attrs_add_backlinks_callback(Slapi_Entry *e, void *callback_data)
+     LDAPMod mod;
+     LDAPMod *mods[2];
+ 
++    /* 
++     * If the server is ordered to shutdown, stop the fixup and return an error.
++     */
++    if (slapi_is_shutting_down()) {
++        rc = -1;
++        goto done;
++    }
+     /* Setup the modify operation.  Only the target will
+      * change, so we only need to do this once. */
+     val[0] = linkdn;
+diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
+index 7e3e308..14bad98 100644
+--- a/ldap/servers/plugins/memberof/memberof.c
++++ b/ldap/servers/plugins/memberof/memberof.c
+@@ -2636,6 +2636,12 @@ void memberof_fixup_task_thread(void *arg)
+ 	int rc = 0;
+ 	Slapi_PBlock *fixup_pb = NULL;
+ 
++	if (!task) {
++		return; /* no task */
++	}
++	slapi_task_inc_refcount(task);
++	slapi_log_error(SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
++	                "memberof_fixup_task_thread --> refcount incremented.\n" );
+ 	/* Fetch our task data from the task */
+ 	td = (task_data *)slapi_task_get_data(task);
+ 
+@@ -2702,6 +2708,9 @@ void memberof_fixup_task_thread(void *arg)
+ 
+ 	/* this will queue the destruction of the task */
+ 	slapi_task_finish(task, rc);
++	slapi_task_dec_refcount(task);
++	slapi_log_error(SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
++	                "memberof_fixup_task_thread <-- refcount decremented.\n");
+ }
+ 
+ /* extract a single value from the entry (as a string) -- if it's not in the
+@@ -2793,8 +2802,14 @@ out:
+ void
+ memberof_task_destructor(Slapi_Task *task)
+ {
++	slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
++		"memberof_task_destructor -->\n" );
+ 	if (task) {
+ 		task_data *mydata = (task_data *)slapi_task_get_data(task);
++		while (slapi_task_get_refcount(task) > 0) {
++			/* Yield to wait for the fixup task finishes. */
++			DS_Sleep (PR_MillisecondsToInterval(100));
++		}
+ 		if (mydata) {
+ 			slapi_ch_free_string(&mydata->dn);
+ 			slapi_ch_free_string(&mydata->bind_dn);
+@@ -2803,6 +2818,8 @@ memberof_task_destructor(Slapi_Task *task)
+ 			slapi_ch_free((void **)&mydata);
+ 		}
+ 	}
++	slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
++		"memberof_task_destructor <--\n" );
+ }
+ 
+ int memberof_fix_memberof(MemberOfConfig *config, char *dn, char *filter_str)
+@@ -2841,6 +2858,13 @@ int memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data)
+ 	memberof_del_dn_data del_data = {0, config->memberof_attr};
+ 	Slapi_ValueSet *groups = 0;
+ 
++	/* 
++	 * If the server is ordered to shutdown, stop the fixup and return an error.
++	 */
++	if (slapi_is_shutting_down()) {
++		rc = -1;
++		goto bail;
++	}
+ 	/* get a list of all of the groups this user belongs to */
+ 	groups = memberof_get_groups(config, sdn);
+ 
+@@ -2889,6 +2913,6 @@ int memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data)
+ 	}
+ 
+ 	slapi_valueset_free(groups);
+-	
++bail:
+ 	return rc;
+ }
+diff --git a/ldap/servers/plugins/memberof/memberof.h b/ldap/servers/plugins/memberof/memberof.h
+index 6d56081..59029d7 100644
+--- a/ldap/servers/plugins/memberof/memberof.h
++++ b/ldap/servers/plugins/memberof/memberof.h
+@@ -81,7 +81,7 @@ typedef struct memberofconfig {
+ 	char *memberof_attr;
+ 	int allBackends;
+ 	Slapi_DN *entryScope;
+-        Slapi_DN *entryScopeExcludeSubtree;
++	Slapi_DN *entryScopeExcludeSubtree;
+ 	Slapi_Filter *group_filter;
+ 	Slapi_Attr **group_slapiattrs;
+ } MemberOfConfig;
+diff --git a/ldap/servers/plugins/posix-winsync/posix-group-task.c b/ldap/servers/plugins/posix-winsync/posix-group-task.c
+index c5ea729..c76545a 100644
+--- a/ldap/servers/plugins/posix-winsync/posix-group-task.c
++++ b/ldap/servers/plugins/posix-winsync/posix-group-task.c
+@@ -165,6 +165,10 @@ posix_group_task_destructor(Slapi_Task *task)
+ {
+     if (task) {
+         task_data *mydata = (task_data *) slapi_task_get_data(task);
++        while (slapi_task_get_refcount(task) > 0) {
++            /* Yield to wait for the fixup task finishes. */
++            DS_Sleep (PR_MillisecondsToInterval(100));
++        }
+         if (mydata) {
+             slapi_ch_free_string(&mydata->dn);
+             slapi_ch_free_string(&mydata->filter_str);
+@@ -172,6 +176,8 @@ posix_group_task_destructor(Slapi_Task *task)
+             slapi_ch_free((void **) &mydata);
+         }
+     }
++    slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME,
++                    "posix_group_task_destructor <--\n");
+ }
+ 
+ #if 0 /* NOT USED */
+@@ -245,17 +251,28 @@ posix_group_fix_memberuid_callback(Slapi_Entry *e, void *callback_data)
+                     "_fix_memberuid ==>\n");
+     cb_data *the_cb_data = (cb_data *) callback_data;
+ 
+-    int rc;
++    int rc = 0;
+     Slapi_Attr *muid_attr = NULL;
+     Slapi_Value *v = NULL;
+ 
+-    Slapi_Mods *smods = slapi_mods_new();
+-
+-    char *dn = slapi_entry_get_dn(e);
+-    Slapi_DN *sdn = slapi_entry_get_sdn(e);
++    Slapi_Mods *smods = NULL;
++    char *dn = NULL;
++    Slapi_DN *sdn = NULL;
+     LDAPMod **mods = NULL;
+     int is_posix_group = 0;
+ 
++    /* 
++     * If the server is ordered to shutdown, stop the fixup and return an error.
++     */
++    if (slapi_is_shutting_down()) {
++        rc = -1;
++        goto bail;
++    }
++
++    smods = slapi_mods_new();
++    dn = slapi_entry_get_dn(e);
++    sdn = slapi_entry_get_sdn(e);
++
+     if (hasObjectClass(e, "posixGroup")) {
+         is_posix_group = 1;
+     }
+@@ -441,7 +458,7 @@ posix_group_fix_memberuid_callback(Slapi_Entry *e, void *callback_data)
+         slapi_pblock_destroy(mod_pb);
+     }
+     slapi_mods_free(&smods);
+-
++bail:
+     slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME,
+                     "_fix_memberuid <==\n");
+     /*
+@@ -450,7 +467,7 @@ posix_group_fix_memberuid_callback(Slapi_Entry *e, void *callback_data)
+      * uniqueMember attribute.  But "not found" error shoud not
+      * be returned, which stops the further fixup task.
+      */
+-    return 0;
++    return rc;
+ }
+ 
+ static void
+@@ -463,6 +480,12 @@ posix_group_fixup_task_thread(void *arg)
+     task_data *td = NULL;
+     int rc = 0;
+ 
++    if (!task) {
++        return; /* no task */
++    }
++    slapi_task_inc_refcount(task);
++    slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME,
++                    "posix_group_fixup_task_thread --> refcount incremented.\n" );
+     /* Fetch our task data from the task */
+     td = (task_data *) slapi_task_get_data(task);
+ 
+@@ -491,4 +514,7 @@ posix_group_fixup_task_thread(void *arg)
+ 
+     slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME,
+                     "_task_thread <==\n");
++    slapi_task_dec_refcount(task);
++    slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME,
++                    "posix_group_fixup_task_thread <-- refcount decremented.\n");
+ }
+diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
+index 3bc3916..1570ba7 100644
+--- a/ldap/servers/plugins/replication/repl5_replica_config.c
++++ b/ldap/servers/plugins/replication/repl5_replica_config.c
+@@ -109,6 +109,8 @@ static CSN* replica_cleanallruv_find_maxcsn(Replica *replica, ReplicaId rid, cha
+ static int replica_cleanallruv_get_replica_maxcsn(Repl_Agmt *agmt, char *rid_text, char *basedn, CSN **csn);
+ static void preset_cleaned_rid(ReplicaId rid);
+ static multimaster_mtnode_extension * _replica_config_get_mtnode_ext (const Slapi_Entry *e);
++static void replica_cleanall_ruv_destructor(Slapi_Task *task);
++static void replica_cleanall_ruv_abort_destructor(Slapi_Task *task);
+ 
+ /*
+  * Note: internal add/modify/delete operations should not be run while
+@@ -1509,6 +1511,10 @@ replica_cleanall_ruv_task(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
+         rc = SLAPI_DSE_CALLBACK_ERROR;
+         goto out;
+     }
++
++    /* register our destructor for waiting the task is done */
++    slapi_task_set_destructor_fn(task, replica_cleanall_ruv_destructor);
++
+     /*
+      *  Get our task settings
+      */
+@@ -1752,6 +1758,13 @@ replica_cleanallruv_thread(void *arg)
+     int aborted = 0;
+     int rc = 0;
+ 
++    if (!data) {
++        return; /* no data */
++    }
++    if (data->task) {
++        slapi_task_inc_refcount(data->task);
++        slapi_log_error(SLAPI_LOG_PLUGIN, repl_plugin_name, "replica_cleanallruv_thread --> refcount incremented.\n");
++    }
+     /*
+      *  Initialize our settings
+      */
+@@ -1974,6 +1987,8 @@ done:
+     }
+     if(data->task){
+         slapi_task_finish(data->task, rc);
++        slapi_task_dec_refcount(data->task);
++        slapi_log_error(SLAPI_LOG_PLUGIN, repl_plugin_name, "replica_cleanallruv_thread <-- refcount decremented.\n");
+     }
+     if(data->payload){
+         ber_bvfree(data->payload);
+@@ -1989,6 +2004,36 @@ done:
+     slapi_ch_free((void **)&data);
+ }
+ 
++static void
++replica_cleanall_ruv_destructor(Slapi_Task *task)
++{
++	slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name,
++		"replica_cleanall_ruv_destructor -->\n" );
++	if (task) {
++		while (slapi_task_get_refcount(task) > 0) {
++			/* Yield to wait for the fixup task finishes. */
++			DS_Sleep (PR_MillisecondsToInterval(100));
++		}
++	}
++	slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name,
++		"replica_cleanall_ruv_destructor <--\n" );
++}
++
++static void
++replica_cleanall_ruv_abort_destructor(Slapi_Task *task)
++{
++	slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name,
++		"replica_cleanall_ruv_abort_destructor -->\n" );
++	if (task) {
++		while (slapi_task_get_refcount(task) > 0) {
++			/* Yield to wait for the fixup task finishes. */
++			DS_Sleep (PR_MillisecondsToInterval(100));
++		}
++	}
++	slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name,
++		"replica_cleanall_ruv_abort_destructor <--\n" );
++}
++
+ /*
+  *  Loop over the agmts, and check if they are in the last phase of cleaning, meaning they have
+  *  released cleanallruv data from the config
+@@ -2775,6 +2820,10 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter
+ 
+     /* allocate new task now */
+     task = slapi_new_task(slapi_entry_get_ndn(e));
++
++    /* register our destructor for waiting the task is done */
++    slapi_task_set_destructor_fn(task, replica_cleanall_ruv_abort_destructor);
++
+     /*
+      *  Get our task settings
+      */
+@@ -2921,6 +2970,13 @@ replica_abort_task_thread(void *arg)
+     int release_it = 0;
+     int count = 0, rc = 0;
+ 
++    if (!data) {
++        return; /* no data */
++    }
++    if (data->task) {
++        slapi_task_inc_refcount(data->task);
++        slapi_log_error(SLAPI_LOG_PLUGIN, repl_plugin_name, "replica_abort_task_thread --> refcount incremented.\n");
++    }
+     cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Aborting task for rid(%d)...",data->rid);
+ 
+     /*
+@@ -3028,6 +3084,8 @@ done:
+ 
+     if(data->task){
+         slapi_task_finish(data->task, agmt_not_notified);
++        slapi_task_dec_refcount(data->task);
++        slapi_log_error(SLAPI_LOG_PLUGIN, repl_plugin_name, "replica_abort_task_thread <-- refcount incremented.\n");
+     }
+     if(data->repl_obj && release_it)
+         object_release(data->repl_obj);
+diff --git a/ldap/servers/plugins/schema_reload/schema_reload.c b/ldap/servers/plugins/schema_reload/schema_reload.c
+index b1a5bb8..25336fe 100644
+--- a/ldap/servers/plugins/schema_reload/schema_reload.c
++++ b/ldap/servers/plugins/schema_reload/schema_reload.c
+@@ -86,6 +86,7 @@ static int schemareload_add(Slapi_PBlock *pb, Slapi_Entry *e,
+                     void *arg);
+ static int schemareload_start(Slapi_PBlock *pb);
+ static int schemareload_close(Slapi_PBlock *pb);
++static void schemareload_destructor(Slapi_Task *task);
+ 
+ /* 
+  * Init function
+@@ -159,6 +160,12 @@ schemareload_thread(void *arg)
+     int total_work = 2;
+     task_data *td = NULL;
+ 
++    if (!task) {
++        return; /* no task */
++    }
++    slapi_task_inc_refcount(task);
++    slapi_log_error(SLAPI_LOG_PLUGIN, "schemareload",
++                    "schemareload_thread --> refcount incremented.\n" );
+     /* Fetch our task data from the task */
+     td = (task_data *)slapi_task_get_data(task);
+ 
+@@ -174,7 +181,11 @@ schemareload_thread(void *arg)
+     rv = slapi_validate_schema_files(td->schemadir);
+     slapi_task_inc_progress(task);
+ 
+-    if (LDAP_SUCCESS == rv) {
++    if (slapi_is_shutting_down()) {
++        slapi_task_log_notice(task, "Server is shuttoing down; Schema validation aborted.");
++        slapi_task_log_status(task, "Server is shuttoing down; Schema validation aborted.");
++        slapi_log_error(SLAPI_LOG_FATAL, "schemareload", "Server is shuttoing down; Schema validation aborted.");
++    } else if (LDAP_SUCCESS == rv) {
+         slapi_task_log_notice(task, "Schema validation passed.");
+         slapi_task_log_status(task, "Schema validation passed.");
+         slapi_log_error(SLAPI_LOG_FATAL, "schemareload", "Schema validation passed.\n");
+@@ -199,16 +210,18 @@ schemareload_thread(void *arg)
+             slapi_task_log_status(task, "Schema reload task failed.");
+             slapi_log_error(SLAPI_LOG_FATAL, "schemareload", "Schema reload task failed.\n");
+         }
+-        PR_Unlock(schemareload_lock);
+     } else {
+         slapi_task_log_notice(task, "Schema validation failed.");
+         slapi_task_log_status(task, "Schema validation failed.");
+         slapi_log_error(SLAPI_LOG_FATAL, "schemareload", "Schema validation failed.\n");
+-        PR_Unlock(schemareload_lock);
+     }
++    PR_Unlock(schemareload_lock);
+ 
+     /* this will queue the destruction of the task */
+     slapi_task_finish(task, rv);
++    slapi_task_dec_refcount(task);
++    slapi_log_error(SLAPI_LOG_PLUGIN, "schemareload",
++                    "schemareload_thread <-- refcount decremented.\n");
+ }
+ 
+ /* extract a single value from the entry (as a string) -- if it's not in the
+@@ -233,6 +246,10 @@ schemareload_destructor(Slapi_Task *task)
+ {
+     if (task) {
+         task_data *mydata = (task_data *)slapi_task_get_data(task);
++        while (slapi_task_get_refcount(task) > 0) {
++            /* Yield to wait for the fixup task finishes. */
++            DS_Sleep (PR_MillisecondsToInterval(100));
++        }
+         if (mydata) {
+             slapi_ch_free_string(&mydata->schemadir);
+             slapi_ch_free_string(&mydata->bind_dn);
+diff --git a/ldap/servers/plugins/syntaxes/validate_task.c b/ldap/servers/plugins/syntaxes/validate_task.c
+index 99f6309..71b4b7e 100644
+--- a/ldap/servers/plugins/syntaxes/validate_task.c
++++ b/ldap/servers/plugins/syntaxes/validate_task.c
+@@ -179,6 +179,10 @@ syntax_validate_task_destructor(Slapi_Task *task)
+ {
+ 	if (task) {
+ 		task_data *mydata = (task_data *)slapi_task_get_data(task);
++		while (slapi_task_get_refcount(task) > 0) {
++			/* Yield to wait for the fixup task finishes. */
++			DS_Sleep (PR_MillisecondsToInterval(100));
++		}
+ 		if (mydata) {
+ 			slapi_ch_free_string(&mydata->dn);
+ 			slapi_ch_free_string(&mydata->filter_str);
+@@ -197,6 +201,12 @@ syntax_validate_task_thread(void *arg)
+ 	task_data *td = NULL;
+ 	Slapi_PBlock *search_pb = slapi_pblock_new();
+ 
++	if (!task) {
++		return; /* no task */
++	}
++	slapi_task_inc_refcount(task);
++	slapi_log_error(SLAPI_LOG_PLUGIN, SYNTAX_PLUGIN_SUBSYSTEM,
++	                "syntax_validate_task_thread --> refcount incremented.\n" );
+ 	/* Fetch our task data from the task */
+ 	td = (task_data *)slapi_task_get_data(task);
+ 
+@@ -231,16 +241,26 @@ syntax_validate_task_thread(void *arg)
+ 
+ 	/* this will queue the destruction of the task */
+ 	slapi_task_finish(task, rc);
++	slapi_task_dec_refcount(task);
++	slapi_log_error(SLAPI_LOG_PLUGIN, SYNTAX_PLUGIN_SUBSYSTEM,
++	                "syntax_validate_task_thread <-- refcount decremented.\n"); 
+ }
+ 
+ static int
+ syntax_validate_task_callback(Slapi_Entry *e, void *callback_data)
+ {
+-        int rc = 0;
+-        char *dn = slapi_entry_get_dn(e);
++	int rc = 0;
++	char *dn = slapi_entry_get_dn(e);
+ 	task_data *td = (task_data *)callback_data;
+ 	Slapi_PBlock *pb = NULL;
+ 
++	/* 
++	 * If the server is ordered to shutdown, stop the fixup and return an error.
++	 */
++	if (slapi_is_shutting_down()) {
++		rc = -1;
++		goto bail;
++	}
+ 	/* Override the syntax checking config to force syntax checking. */
+ 	if (slapi_entry_syntax_check(NULL, e, 1) != 0) {
+ 		char *error_text = NULL;
+@@ -261,7 +281,7 @@ syntax_validate_task_callback(Slapi_Entry *e, void *callback_data)
+ 		/* Keep a tally of the number of invalid entries found. */
+ 		slapi_counter_increment(td->invalid_entries);
+ 	}
+-
++bail:
+ 	return rc;
+ }
+ 
+diff --git a/ldap/servers/plugins/usn/usn_cleanup.c b/ldap/servers/plugins/usn/usn_cleanup.c
+index c12dfd2..dd07b4c 100644
+--- a/ldap/servers/plugins/usn/usn_cleanup.c
++++ b/ldap/servers/plugins/usn/usn_cleanup.c
+@@ -49,6 +49,8 @@ struct usn_cleanup_data {
+ 
+ static int usn_cleanup_add(Slapi_PBlock *pb, Slapi_Entry *e,
+             Slapi_Entry *eAfter, int *returncode, char *returntext, void *arg);
++static void usn_cleanup_task_destructor(Slapi_Task *task);
++
+ 
+ int
+ usn_cleanup_start(Slapi_PBlock *pb)
+@@ -83,8 +85,14 @@ usn_cleanup_thread(void *arg)
+     Slapi_PBlock *delete_pb = NULL;
+     char *filter = "objectclass=nsTombstone";
+ 
++	if (!task) {
++		return; /* no task */
++	}
+     slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+                     "--> usn_cleanup_thread\n");
++	slapi_task_inc_refcount(task);
++	slapi_log_error(SLAPI_LOG_PLUGIN, USN_PLUGIN_SUBSYSTEM,
++	                "usn_cleanup_thread --> refcount incremented.\n" );
+ 
+     if (NULL == usn_get_identity()) { /* plugin is not initialized */
+         slapi_task_log_notice(task, "USN plugin is not initialized\n");
+@@ -195,14 +203,12 @@ bail:
+     if (cleanup_data->maxusn_to_delete) {
+         slapi_ch_free_string(&filter);
+     }
+-    slapi_ch_free_string(&cleanup_data->maxusn_to_delete);
+-    slapi_ch_free_string(&cleanup_data->suffix);
+-    slapi_ch_free_string(&cleanup_data->bind_dn);
+-    slapi_ch_free((void **)&cleanup_data);
+ 
+     /* this will queue the destruction of the task */
+     slapi_task_finish(task, rv);
+-
++	slapi_task_dec_refcount(task);
++	slapi_log_error(SLAPI_LOG_PLUGIN, USN_PLUGIN_SUBSYSTEM,
++	                "usn_cleanup_thread <-- refcount decremented.\n");
+     slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+                     "<-- usn_cleanup_thread\n");
+ }
+@@ -283,7 +289,7 @@ usn_cleanup_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
+     backend = slapi_entry_attr_get_charptr(e, "backend");
+     maxusn = slapi_entry_attr_get_charptr(e, "maxusn_to_delete");
+ 
+-    if (NULL == suffix && NULL == backend) {
++    if (!suffix && !backend) {
+         slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+             "USN tombstone cleanup: Both suffix and backend are missing.\n");
+         *returncode = LDAP_PARAM_ERROR;
+@@ -292,7 +298,7 @@ usn_cleanup_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
+     }
+ 
+     /* suffix is not given, but backend is; get the suffix */
+-    if (NULL == suffix && NULL != backend) {
++    if (!suffix && backend) {
+         be = slapi_be_select_by_instance_name(backend);
+         be_suffix = slapi_be_getsuffix(be, 0);
+         if (be_suffix) {
+@@ -317,12 +323,6 @@ usn_cleanup_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
+         goto bail;
+     }
+ 
+-    cleanup_data =
+-      (struct usn_cleanup_data *)slapi_ch_malloc(sizeof(struct usn_cleanup_data));
+-    cleanup_data->suffix = slapi_ch_strdup(suffix);
+-    cleanup_data->maxusn_to_delete = slapi_ch_strdup(maxusn);
+-    cleanup_data->bind_dn = slapi_ch_strdup(bind_dn);
+-
+     /* allocate new task now */
+     task = slapi_plugin_new_task(slapi_entry_get_ndn(e), arg);
+     if (task == NULL) {
+@@ -330,11 +330,21 @@ usn_cleanup_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
+             "USN tombstone cleanup: unable to allocate new task.\n");
+         *returncode = LDAP_OPERATIONS_ERROR;
+         rv = SLAPI_DSE_CALLBACK_ERROR;
+-        slapi_ch_free((void**)&cleanup_data);
+         goto bail;
+     }
+ 
++    /* register our destructor for cleaning up our private data */
++    slapi_task_set_destructor_fn(task, usn_cleanup_task_destructor);
++
+     /* Stash our argument in the task for use by the task thread */
++    cleanup_data =
++      (struct usn_cleanup_data *)slapi_ch_malloc(sizeof(struct usn_cleanup_data));
++    cleanup_data->suffix = suffix;
++	suffix = NULL; /* don't free in this function */
++    cleanup_data->maxusn_to_delete = maxusn;
++	maxusn = NULL; /* don't free in this function */
++    cleanup_data->bind_dn = bind_dn;
++    bind_dn = NULL; /* don't free in this function */
+     slapi_task_set_data(task, cleanup_data);
+ 
+     /* start the USN tombstone cleanup task as a separate thread */
+@@ -361,3 +371,23 @@ bail:
+     return rv;
+ }
+ 
++static void
++usn_cleanup_task_destructor(Slapi_Task *task)
++{
++    slapi_log_error(SLAPI_LOG_PLUGIN, USN_PLUGIN_SUBSYSTEM, "usn_cleanup_task_destructor -->\n");
++    if (task) {
++        struct usn_cleanup_data *mydata = (struct usn_cleanup_data *)slapi_task_get_data(task);
++        while (slapi_task_get_refcount(task) > 0) {
++            /* Yield to wait for the fixup task finishes. */
++            DS_Sleep (PR_MillisecondsToInterval(100));
++        }
++        if (mydata) {
++            slapi_ch_free_string(&mydata->suffix);
++            slapi_ch_free_string(&mydata->maxusn_to_delete);
++            slapi_ch_free_string(&mydata->bind_dn);
++            /* Need to cast to avoid a compiler warning */
++            slapi_ch_free((void **)&mydata);
++        }
++    }
++    slapi_log_error(SLAPI_LOG_PLUGIN, USN_PLUGIN_SUBSYSTEM, "usn_cleanup_task_destructor <--\n");
++}
+diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
+index 0ae3601..dfe75eb 100644
+--- a/ldap/servers/slapd/slapi-plugin.h
++++ b/ldap/servers/slapd/slapi-plugin.h
+@@ -7958,6 +7958,15 @@ void slapi_plugin_op_finished(void *arg);
+ #define RDN_IS_CONFLICT  0x2
+ int slapi_is_special_rdn(const char *rdn, int flag);
+ 
++/**
++ * Sleeps for PRIntervalTime ticks defined in NSPR library
++ *
++ * \param PRIntervalTime ticks
++ *
++ * \return Nothing
++ */
++void    DS_Sleep(PRIntervalTime ticks);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
+index 921c397..9ca1950 100644
+--- a/ldap/servers/slapd/slapi-private.h
++++ b/ldap/servers/slapd/slapi-private.h
+@@ -1245,8 +1245,6 @@ void bervalarray_add_berval_fast(struct berval ***vals, const struct berval *add
+ 
+ /***** End of items added for the replication plugin. ***********************/
+ 
+-void    DS_Sleep(PRIntervalTime ticks);
+-
+ /* macro to specify the behavior of upgradedb & upgradednformat */
+ #define SLAPI_UPGRADEDB_FORCE    0x1  /* reindex all (no check w/ idl switch) */
+ #define SLAPI_UPGRADEDB_SKIPINIT 0x2  /* call upgradedb as part of other op */
+diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
+index 98ec88c..19a52a3 100644
+--- a/ldap/servers/slapd/task.c
++++ b/ldap/servers/slapd/task.c
+@@ -113,6 +113,8 @@ static const char *fetch_attr(Slapi_Entry *e, const char *attrname,
+ static Slapi_Entry *get_internal_entry(Slapi_PBlock *pb, char *dn);
+ static void modify_internal_entry(char *dn, LDAPMod **mods);
+ 
++static void fixup_tombstone_task_destructor(Slapi_Task *task);
++
+ /***********************************
+  * Public Functions
+  ***********************************/ 
+@@ -2218,6 +2220,12 @@ task_fixup_tombstone_thread(void *arg)
+     int fixup_count = 0;
+     int rc, i, j;
+ 
++    if (!task) {
++        return; /* no task */
++    }
++    slapi_task_inc_refcount(task);
++    slapi_log_error(SLAPI_LOG_PLUGIN, TASK_TOMBSTONE_FIXUP,
++                    "fixup_tombstone_task_thread --> refcount incremented.\n" );
+     slapi_task_begin(task, 1);
+     slapi_task_log_notice(task, "Beginning tombstone fixup task...\n");
+     slapi_log_error(SLAPI_LOG_REPL, TASK_TOMBSTONE_FIXUP,
+@@ -2233,8 +2241,14 @@ task_fixup_tombstone_thread(void *arg)
+ 
+     /* Okay check the specified backends only */
+     for(i = 0; base && base[i]; i++){
+-        Slapi_PBlock *search_pb = slapi_pblock_new();
++        Slapi_PBlock *search_pb = NULL;
++
++        if (slapi_is_shutting_down()) {
++            rc = -1;
++            goto bail;
++        }
+ 
++        search_pb = slapi_pblock_new();
+         /* find entries that need fixing... */
+         slapi_search_internal_set_pb(search_pb, base[i], LDAP_SCOPE_SUBTREE,
+                 filter, NULL, 0, NULL, NULL, plugin_get_default_component_id(), 0);
+@@ -2247,8 +2261,7 @@ task_fixup_tombstone_thread(void *arg)
+             slapi_log_error(SLAPI_LOG_REPL, TASK_TOMBSTONE_FIXUP,
+                     "Failed to search backend for tombstones, error %d\n", rc);
+             slapi_pblock_destroy(search_pb);
+-            slapi_task_finish(task, rc);
+-            return;
++            goto bail;
+         }
+ 
+         slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+@@ -2281,9 +2294,11 @@ task_fixup_tombstone_thread(void *arg)
+     slapi_log_error(SLAPI_LOG_REPL, TASK_TOMBSTONE_FIXUP, "%s %d tombstones.\n",
+                     task_data->stripcsn ? "Stripped" : "Fixed", fixup_count);
+     slapi_task_inc_progress(task);
++bail:
+     slapi_task_finish(task, rc);
+-    slapi_ch_array_free(base);
+-    slapi_ch_free((void **)&task_data);
++    slapi_task_dec_refcount(task);
++    slapi_log_error(SLAPI_LOG_PLUGIN, TASK_TOMBSTONE_FIXUP,
++                    "fixup_tombstone_task_thread <-- refcount decremented.\n" );
+ }
+ 
+ 
+@@ -2387,6 +2402,8 @@ task_fixup_tombstones_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
+     }
+ 
+     task = slapi_new_task(slapi_entry_get_ndn(e));
++    /* register our destructor for cleaning up our private data */
++    slapi_task_set_destructor_fn(task, fixup_tombstone_task_destructor);
+     task_data = (struct task_tombstone_data *)slapi_ch_calloc(1, sizeof(struct task_tombstone_data));
+     task_data->base = base;
+     task_data->task = task;
+@@ -2422,6 +2439,26 @@ done:
+     return SLAPI_DSE_CALLBACK_OK;
+ }
+ 
++static void
++fixup_tombstone_task_destructor(Slapi_Task *task)
++{
++    slapi_log_error(SLAPI_LOG_PLUGIN, TASK_TOMBSTONE_FIXUP,
++                    "fixup_tombstone_task_destructor -->\n" );
++    if (task) {
++        struct task_tombstone_data *mydata = (struct task_tombstone_data *)slapi_task_get_data(task);
++        while (slapi_task_get_refcount(task) > 0) {
++            /* Yield to wait for the fixup task finishes. */
++            DS_Sleep (PR_MillisecondsToInterval(100));
++        }
++        if (mydata) {
++            slapi_ch_array_free(mydata->base);
++            slapi_ch_free((void **)&mydata);
++        }
++    }
++    slapi_log_error(SLAPI_LOG_PLUGIN, TASK_TOMBSTONE_FIXUP,
++                    "fixup_tombstone_task_destructor <--\n" );
++}
++
+ /* cleanup old tasks that may still be in the DSE from a previous session
+  * (this can happen if the server crashes [no matter how unlikely we like
+  * to think that is].)
+-- 
+1.9.3
+
diff --git a/SOURCES/0062-CVE-2015-1854-389ds-base-access-control-bypass-with-.patch b/SOURCES/0062-CVE-2015-1854-389ds-base-access-control-bypass-with-.patch
new file mode 100644
index 0000000..903a69d
--- /dev/null
+++ b/SOURCES/0062-CVE-2015-1854-389ds-base-access-control-bypass-with-.patch
@@ -0,0 +1,347 @@
+From 205bce153c7db8258a8a28498cf54e7374dca588 Mon Sep 17 00:00:00 2001
+From: Thierry Bordaz <tbordaz@redhat.com>
+Date: Tue, 14 Apr 2015 16:24:44 +0200
+Subject: [PATCH] CVE-2015-1854 389ds-base: access control bypass with modrdn
+
+Bug Description:
+	47553 fix checks the write right access only if the RDN is
+	modified. This allows to rename entries even if the
+	authenticated user is not allowed of that.
+
+Fix Description:
+	Roll back a wrong optimization that tested the write access
+	only if RDN value was changed.
+
+https://fedorahosted.org/389/ticket/47553
+
+Reviewed by: ?
+
+Platforms tested: F17 (upstream test)
+
+Flag Day: no
+
+Doc impact: no
+
+(cherry picked from commit 44e5c0998bdf7dcb167e8472713ff393b776e4e3)
+
+Conflicts:
+	dirsrvtests/tickets/ticket47553_single_aci_test.py
+---
+ dirsrvtests/tickets/ticket47553_rdn_write_test.py  | 132 +++++++++++++++++++++
+ dirsrvtests/tickets/ticket47553_single_aci_test.py |  52 ++++++--
+ ldap/servers/slapd/back-ldbm/ldbm_modrdn.c         |  32 ++---
+ 3 files changed, 184 insertions(+), 32 deletions(-)
+ create mode 100644 dirsrvtests/tickets/ticket47553_rdn_write_test.py
+
+diff --git a/dirsrvtests/tickets/ticket47553_rdn_write_test.py b/dirsrvtests/tickets/ticket47553_rdn_write_test.py
+new file mode 100644
+index 0000000..f15d9b3
+--- /dev/null
++++ b/dirsrvtests/tickets/ticket47553_rdn_write_test.py
+@@ -0,0 +1,132 @@
++import os
++import sys
++import time
++import ldap
++import logging
++import pytest
++from lib389 import DirSrv, Entry, tools, tasks
++from lib389.tools import DirSrvTools
++from lib389._constants import *
++from lib389.properties import *
++from lib389.tasks import *
++from lib389.utils import *
++from ldap.controls.simple import GetEffectiveRightsControl
++
++logging.getLogger(__name__).setLevel(logging.DEBUG)
++log = logging.getLogger(__name__)
++
++installation1_prefix = None
++
++SRC_ENTRY_CN = "tuser"
++EXT_RDN = "01"
++DST_ENTRY_CN = SRC_ENTRY_CN + EXT_RDN
++
++SRC_ENTRY_DN = "cn=%s,%s" % (SRC_ENTRY_CN, SUFFIX)
++DST_ENTRY_DN = "cn=%s,%s" % (DST_ENTRY_CN, SUFFIX)
++
++class TopologyStandalone(object):
++    def __init__(self, standalone):
++        standalone.open()
++        self.standalone = standalone
++
++
++#@pytest.fixture(scope="module")
++def topology(request):
++    global installation1_prefix
++
++    # Creating standalone instance ...
++    standalone = DirSrv(verbose=False)
++    if installation1_prefix:
++        args_instance[SER_DEPLOYED_DIR] = installation1_prefix
++    args_instance[SER_HOST] = HOST_STANDALONE
++    args_instance[SER_PORT] = PORT_STANDALONE
++    args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
++    args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
++    args_standalone = args_instance.copy()
++    standalone.allocate(args_standalone)
++    instance_standalone = standalone.exists()
++    if instance_standalone:
++        standalone.delete()
++    standalone.create()
++    standalone.open()
++
++    # Clear out the tmp dir
++    standalone.clearTmpDir(__file__)
++
++    return TopologyStandalone(standalone)
++
++def test_ticket47553_rdn_write_init(topology):
++    topology.standalone.log.info("\n\n######################### Add entry tuser ######################\n")
++    topology.standalone.add_s(Entry((SRC_ENTRY_DN, {
++                                                'objectclass': "top person".split(),
++                                                'sn': SRC_ENTRY_CN,
++                                                'cn': SRC_ENTRY_CN})))
++
++def test_ticket47553_rdn_write_get_ger(topology):
++    ANONYMOUS_DN = ""
++    topology.standalone.log.info("\n\n######################### GER rights for anonymous ######################\n")
++    request_ctrl = GetEffectiveRightsControl(criticality=True, authzId="dn:" + ANONYMOUS_DN)
++    msg_id = topology.standalone.search_ext(SUFFIX, ldap.SCOPE_SUBTREE, "objectclass=*", serverctrls=[request_ctrl])
++    rtype, rdata, rmsgid, response_ctrl = topology.standalone.result3(msg_id)
++    value = ''
++    for dn, attrs in rdata:
++        topology.standalone.log.info("dn: %s" % dn)
++        for value in attrs['entryLevelRights']:
++            topology.standalone.log.info("###############  entryLevelRights: %r" % value)
++            assert 'n' not in value
++
++def test_ticket47553_rdn_write_modrdn_anonymous(topology):
++    ANONYMOUS_DN = ""
++    topology.standalone.close()
++    topology.standalone.binddn = ANONYMOUS_DN
++    topology.standalone.open()
++    msg_id = topology.standalone.search_ext("", ldap.SCOPE_BASE, "objectclass=*")
++    rtype, rdata, rmsgid, response_ctrl = topology.standalone.result3(msg_id)
++    value = ''
++    for dn, attrs in rdata:
++        topology.standalone.log.info("dn: %s" % dn)
++        for attr in attrs:
++            topology.standalone.log.info("###############  %r: %r" % (attr, attrs[attr]))
++
++
++    try:
++        topology.standalone.rename_s(SRC_ENTRY_DN, "cn=%s" % DST_ENTRY_CN, delold=True)
++    except Exception as e:
++        topology.standalone.log.info("Exception (expected): %s" % type(e).__name__)
++        isinstance(e, ldap.INSUFFICIENT_ACCESS)
++
++    try:
++        topology.standalone.getEntry(DST_ENTRY_DN, ldap.SCOPE_BASE, "objectclass=*")
++        assert False
++    except Exception as e:
++        topology.standalone.log.info("The entry was not renamed (expected)")
++        isinstance(e, ldap.NO_SUCH_OBJECT)
++
++def test_ticket47553_rdn_write(topology):
++    '''
++    Write your testcase here...
++    '''
++
++    log.info('Test complete')
++
++
++def test_ticket47553_rdn_write_final(topology):
++    topology.standalone.delete()
++    log.info('Testcase PASSED')
++
++
++def run_isolated():
++    global installation1_prefix
++    installation1_prefix = '/home/tbordaz/install_master'
++
++    topo = topology(True)
++    test_ticket47553_rdn_write_init(topo)
++    test_ticket47553_rdn_write_get_ger(topo)
++    test_ticket47553_rdn_write(topo)
++    test_ticket47553_rdn_write_modrdn_anonymous(topo)
++    test_ticket47553_rdn_write_final(topo)
++
++
++if __name__ == '__main__':
++    run_isolated()
++
+diff --git a/dirsrvtests/tickets/ticket47553_single_aci_test.py b/dirsrvtests/tickets/ticket47553_single_aci_test.py
+index 4be2470..0c8d7e9 100644
+--- a/dirsrvtests/tickets/ticket47553_single_aci_test.py
++++ b/dirsrvtests/tickets/ticket47553_single_aci_test.py
+@@ -276,7 +276,27 @@ def _moddn_aci_deny_tree(topology, mod_type=None, target_from=STAGING_DN, target
+     #topology.master1.modify_s(SUFFIX, mod)
+     topology.master1.log.info("Add a DENY aci under %s " % PROD_EXCEPT_DN)
+     topology.master1.modify_s(PROD_EXCEPT_DN, mod)
+-    
++
++def _write_aci_staging(topology, mod_type=None):
++    assert mod_type is not None
++
++    ACI_TARGET = "(targetattr= \"cn\")(target=\"ldap:///cn=*,%s\")" % STAGING_DN
++    ACI_ALLOW        = "(version 3.0; acl \"write staging entries\"; allow (write)"
++    ACI_SUBJECT      = " userdn = \"ldap:///%s\";)" % BIND_DN
++    ACI_BODY         = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT
++    mod = [(mod_type, 'aci', ACI_BODY)]
++    topology.master1.modify_s(SUFFIX, mod)
++
++def _write_aci_production(topology, mod_type=None):
++    assert mod_type is not None
++
++    ACI_TARGET = "(targetattr= \"cn\")(target=\"ldap:///cn=*,%s\")" % PRODUCTION_DN
++    ACI_ALLOW        = "(version 3.0; acl \"write production entries\"; allow (write)"
++    ACI_SUBJECT      = " userdn = \"ldap:///%s\";)" % BIND_DN
++    ACI_BODY         = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT
++    mod = [(mod_type, 'aci', ACI_BODY)]
++    topology.master1.modify_s(SUFFIX, mod)
++
+ def _moddn_aci_staging_to_production(topology, mod_type=None, target_from=STAGING_DN, target_to=PRODUCTION_DN):
+     assert mod_type != None
+ 
+@@ -293,6 +313,8 @@ def _moddn_aci_staging_to_production(topology, mod_type=None, target_from=STAGIN
+     ACI_BODY         = ACI_TARGET_FROM + ACI_TARGET_TO + ACI_ALLOW + ACI_SUBJECT
+     mod = [(mod_type, 'aci', ACI_BODY)]
+     topology.master1.modify_s(SUFFIX, mod)
++    
++    _write_aci_staging(topology, mod_type=mod_type)
+ 
+ def _moddn_aci_from_production_to_staging(topology, mod_type=None):
+     assert mod_type != None
+@@ -303,6 +325,8 @@ def _moddn_aci_from_production_to_staging(topology, mod_type=None):
+     ACI_BODY         = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT
+     mod = [(mod_type, 'aci', ACI_BODY)]
+     topology.master1.modify_s(SUFFIX, mod)
++    
++    _write_aci_production(topology, mod_type=mod_type)
+ 
+ 
+ def test_ticket47553_init(topology):
+@@ -347,12 +371,9 @@ def test_ticket47553_init(topology):
+                                             'description': "production except DIT"})))
+     
+     # enable acl error logging
+-    #mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '128')]
+-    #topology.master1.modify_s(DN_CONFIG, mod)
+-    #topology.master2.modify_s(DN_CONFIG, mod)
+-    
+-
+-    
++    mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', str(128+262144))]
++    topology.master1.modify_s(DN_CONFIG, mod)
++    topology.master2.modify_s(DN_CONFIG, mod)
+     
+     
+     # add dummy entries in the staging DIT
+@@ -883,6 +904,7 @@ def test_ticket47553_moddn_staging_prod_9(topology):
+     _bind_manager(topology)
+     mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
+     topology.master1.modify_s(PRODUCTION_DN, mod)
++    _write_aci_staging(topology, mod_type=ldap.MOD_ADD)
+     _bind_normal(topology)
+     
+     topology.master1.log.info("Try to MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
+@@ -891,6 +913,7 @@ def test_ticket47553_moddn_staging_prod_9(topology):
+     _bind_manager(topology)
+     mod = [(ldap.MOD_DELETE, 'aci', ACI_BODY)]
+     topology.master1.modify_s(PRODUCTION_DN, mod)
++    _write_aci_staging(topology, mod_type=ldap.MOD_DELETE)
+     _bind_normal(topology)
+     
+     
+@@ -934,6 +957,7 @@ def test_ticket47553_moddn_staging_prod_9(topology):
+     _bind_manager(topology)
+     mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
+     topology.master1.modify_s(PRODUCTION_DN, mod)
++    _write_aci_staging(topology, mod_type=ldap.MOD_ADD)
+     _bind_normal(topology)
+     
+     try:
+@@ -949,6 +973,7 @@ def test_ticket47553_moddn_staging_prod_9(topology):
+     _bind_manager(topology)
+     mod = [(ldap.MOD_DELETE, 'aci', ACI_BODY)]
+     topology.master1.modify_s(PRODUCTION_DN, mod)
++    _write_aci_staging(topology, mod_type=ldap.MOD_DELETE)
+     _bind_normal(topology)
+     
+     # Add the moddn aci that will be evaluated because of the config flag
+@@ -1009,7 +1034,12 @@ def test_ticket47553_moddn_prod_staging(topology):
+     old_dn  = "%s,%s" % (old_rdn, PRODUCTION_DN)
+     new_rdn = old_rdn
+     new_superior = STAGING_DN
+-    
++
++    # add the write right because we want to check the moddn
++    _bind_manager(topology)
++    _write_aci_production(topology, mod_type=ldap.MOD_ADD)
++    _bind_normal(topology)
++
+     try:
+         topology.master1.log.info("Try to move back MODDN %s -> %s,%s" % (old_dn, new_rdn, new_superior))
+         topology.master1.rename_s(old_dn, new_rdn, newsuperior=new_superior)
+@@ -1019,7 +1049,11 @@ def test_ticket47553_moddn_prod_staging(topology):
+     except Exception as e:
+         topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
+         assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+-    
++
++    _bind_manager(topology)
++    _write_aci_production(topology, mod_type=ldap.MOD_DELETE)
++    _bind_normal(topology)
++
+     # successfull MOD with the both ACI
+     _bind_manager(topology)
+     _moddn_aci_staging_to_production(topology, mod_type=ldap.MOD_DELETE, target_from=STAGING_DN, target_to=PRODUCTION_DN)
+diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+index 6a4982c..4129318 100644
+--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
++++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+@@ -677,31 +677,17 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
+             
+             /* JCMACL - Should be performed before the child check. */
+             /* JCMACL - Why is the check performed against the copy, rather than the existing entry? */
++            /* This check must be performed even if the entry is renamed with its own name 
++             * No optimization here we need to check we have the write access to the target entry
++             */
++            ldap_result_code = plugin_call_acl_plugin(pb, ec->ep_entry,
++                    NULL /*attr*/, NULL /*value*/, SLAPI_ACL_WRITE,
++                    ACLPLUGIN_ACCESS_MODRDN, &errbuf);
++            if (ldap_result_code != LDAP_SUCCESS)
+             {
+-                Slapi_RDN *new_rdn;
+-                Slapi_RDN *old_rdn;
+-
+-                /* Taken from the entry */
+-                old_rdn = slapi_entry_get_srdn(ec->ep_entry);
+-
+-                /* Taken from the request */
+-                new_rdn = slapi_rdn_new();
+-                slapi_sdn_get_rdn(&dn_newrdn, new_rdn);
+-
+-                /* Only if we change the RDN value, we need the write access to the entry */
+-                if (slapi_rdn_compare(old_rdn, new_rdn)) {
+-                        ldap_result_code = plugin_call_acl_plugin(pb, ec->ep_entry,
+-                                NULL /*attr*/, NULL /*value*/, SLAPI_ACL_WRITE,
+-                                ACLPLUGIN_ACCESS_MODRDN, &errbuf);
+-                }
+-
+-                slapi_rdn_free(&new_rdn);
++                goto error_return;
++            }
+ 
+-                if (ldap_result_code != LDAP_SUCCESS) {
+-                        goto error_return;
+-                }
+-            } 
+-        
+             /* Set the new dn to the copy of the entry */
+             slapi_entry_set_sdn( ec->ep_entry, &dn_newdn );
+             if (entryrdn_get_switch()) { /* subtree-rename: on */
+-- 
+1.9.3
+
diff --git a/SPECS/389-ds-base.spec b/SPECS/389-ds-base.spec
index b9fcb60..25d46e8 100644
--- a/SPECS/389-ds-base.spec
+++ b/SPECS/389-ds-base.spec
@@ -25,7 +25,7 @@
 Summary:          389 Directory Server (base)
 Name:             389-ds-base
 Version:          1.3.3.1
-Release:          %{?relprefix}13%{?prerel}%{?dist}
+Release:          %{?relprefix}16%{?prerel}%{?dist}
 License:          GPLv2 with exceptions
 URL:              http://port389.org/
 Group:            System Environment/Daemons
@@ -175,6 +175,8 @@ Patch57:          0057-Ticket-47989-Windows-Sync-accidentally-cleared-raw_e.patc
 Patch58:          0058-Ticket-47991-upgrade-script-fails-if-etc-and-var-are.patch
 Patch59:          0059-Ticket-47988-Schema-learning-mechanism-in-replicatio.patch
 Patch60:          0060-Ticket-47988-Schema-learning-mechanism-in-replicatio.patch
+Patch61:          0061-Ticket-48005-ns-slapd-crash-in-shutdown-phase.patch
+Patch62:          0062-CVE-2015-1854-389ds-base-access-control-bypass-with-.patch
 
 %description
 389 Directory Server is an LDAPv3 compliant server.  The base package includes
@@ -286,6 +288,8 @@ cp %{SOURCE2} README.devel
 %patch58 -p1
 %patch59 -p1
 %patch60 -p1
+%patch61 -p1
+%patch62 -p1
 
 %build
 %if %{use_openldap}
@@ -348,35 +352,44 @@ ninst=0 # number of instances found in total
 if [ -n "$DEBUGPOSTTRANS" ] ; then
    output=$DEBUGPOSTTRANS
 fi
-echo looking for services in %{_sysconfdir}/systemd/system/%{groupname}.wants/* > $output 2>&1 || :
+echo looking for services in %{_sysconfdir}/systemd/system/%{groupname}.wants/* >> $output 2>&1 || :
 for service in %{_sysconfdir}/systemd/system/%{groupname}.wants/* ; do
     if [ ! -f "$service" ] ; then continue ; fi # in case nothing matches
     inst=`echo $service | sed -e 's,%{_sysconfdir}/systemd/system/%{groupname}.wants/,,'`
-    echo found instance $inst - getting status > $output 2>&1 || :
+    echo found instance $inst - getting status >> $output 2>&1 || :
     if /bin/systemctl -q is-active $inst ; then
-       echo instance $inst is running > $output 2>&1 || :
+       echo instance $inst is running >> $output 2>&1 || :
        instances="$instances $inst"
     else
-       echo instance $inst is not running > $output 2>&1 || :
+       echo instance $inst is not running >> $output 2>&1 || :
     fi
     ninst=`expr $ninst + 1`
 done
 if [ $ninst -eq 0 ] ; then
-    echo no instances to upgrade > $output 2>&1 || :
+    echo no instances to upgrade >> $output 2>&1 || :
     exit 0 # have no instances to upgrade - just skip the rest
 fi
 # shutdown all instances
-echo shutting down all instances . . . > $output 2>&1 || :
-/bin/systemctl stop %{groupname} > $output 2>&1 || :
-echo remove pid files . . . > $output 2>&1 || :
+echo shutting down all instances . . . >> $output 2>&1 || :
+for inst in $instances ; do
+    echo stopping instance $inst >> $output 2>&1 || :
+    /bin/systemctl stop $inst >> $output 2>&1 || :
+done
+echo remove pid files . . . >> $output 2>&1 || :
 /bin/rm -f /var/run/%{pkgname}*.pid /var/run/%{pkgname}*.startpid
 # do the upgrade
-echo upgrading instances . . . > $output 2>&1 || :
-%{_sbindir}/setup-ds.pl -l $output -u -s General.UpdateMode=offline > $output 2>&1 || :
+echo upgrading instances . . . >> $output 2>&1 || :
+DEBUGPOSTSETUPOPT=`/usr/bin/echo $DEBUGPOSTSETUP | /usr/bin/sed -e "s/[^d]//g"`
+if [ -n "$DEBUGPOSTSETUPOPT" ] ; then
+    %{_sbindir}/setup-ds.pl -l $output -$DEBUGPOSTSETUPOPT -u -s General.UpdateMode=offline >> $output 2>&1 || :
+else
+    %{_sbindir}/setup-ds.pl -l $output -u -s General.UpdateMode=offline >> $output 2>&1 || :
+fi
+
 # restart instances that require it
 for inst in $instances ; do
-    echo restarting instance $inst > $output 2>&1 || :
-    /bin/systemctl start $inst > $output 2>&1 || :
+    echo restarting instance $inst >> $output 2>&1 || :
+    /bin/systemctl start $inst >> $output 2>&1 || :
 done
 exit 0
 
@@ -437,6 +450,20 @@ fi
 %{_libdir}/%{pkgname}/libns-dshttpd.so*
 
 %changelog
+* Tue Apr 21 2015 Noriko Hosoi <nhosoi@redhat.com> - 1.3.3.1-16
+- release 1.3.3.1-16
+- Resolves: bug 1212894 - CVE-2015-1854 389ds-base: access control bypass with modrdn
+
+* Mon Feb 23 2015 Noriko Hosoi <nhosoi@redhat.com> - 1.3.3.1-15
+- release 1.3.3.1-15
+- Setting correct build tag 'rhel-7.1-z-candidate'
+
+* Mon Feb 23 2015 Noriko Hosoi <nhosoi@redhat.com> - 1.3.3.1-14
+- release 1.3.3.1-14
+- Resolves: bug 1189154 - DNS errors after IPA upgrade due to broken ReplSync (DS 48030)
+            Fixes spec file to make sure all the server instances are stopped before upgrade
+- Resolves: bug 1186548 - ns-slapd crash in shutdown phase (DS 48005)
+
 * Sun Jan 25 2015 Noriko Hosoi <nhosoi@redhat.com> - 1.3.3.1-13
 - release 1.3.3.1-13
 - Resolves: bug 1183655 - Fixed Covscan FORWARD_NULL defects (DS 47988)