Blame SOURCES/0050-Ticket-47451-Dynamic-Plugin-various-fixes.patch

f92ce9
From 78b344ff88f488aa63ccccf464e83ad55ee9e96d Mon Sep 17 00:00:00 2001
f92ce9
From: Mark Reynolds <mreynolds@redhat.com>
f92ce9
Date: Tue, 16 Dec 2014 15:25:35 -0500
f92ce9
Subject: [PATCH 50/53] Ticket 47451 - Dynamic Plugin - various fixes
f92ce9
f92ce9
Description:  The previous commit 0e0848a8385463532d53db94c0c8cae912c30eb4 on
f92ce9
              master branch was wrong, and broke the other plugin tasks.
f92ce9
f92ce9
              Upon further testing, some memory leaks and crashes were detected
f92ce9
              and fixed:
f92ce9
f92ce9
              automember.c - Fix memory leak, and PRCList corruption
f92ce9
              dna.c - Fix crash caused by event context not being freed at plugin stop
f92ce9
              memberof.c - pass in the correct function argument, not the pblock
f92ce9
              rootdn_access.c - Fix memory leak
f92ce9
              plugins/uiduniq/uid.c - Add start and close functions to properly handle plugin restarts
f92ce9
              dse.c - Improve plugin restart handling, and properly handle plugin registration
f92ce9
              plugin.c - Properly wait for a plugin to finish before restarting it.
f92ce9
              task.c - Proprely handle the task function arguments
f92ce9
f92ce9
https://fedorahosted.org/389/ticket/47451
f92ce9
f92ce9
Reviewed by: nhosoi(Thanks!)
f92ce9
f92ce9
(cherry picked from commit ff023a48b7fc78711eed8ae11e67057597acdeb3)
f92ce9
(cherry picked from commit f17159e73ba0851599c4e50c1bf52d3d10f2711f)
f92ce9
---
f92ce9
 ldap/servers/plugins/automember/automember.c       |   4 +-
f92ce9
 ldap/servers/plugins/dna/dna.c                     |  14 ++-
f92ce9
 ldap/servers/plugins/memberof/memberof.c           |   2 +-
f92ce9
 ldap/servers/plugins/rootdn_access/rootdn_access.c |   4 +-
f92ce9
 ldap/servers/plugins/schema_reload/schema_reload.c |   2 +-
f92ce9
 ldap/servers/plugins/uiduniq/uid.c                 |  63 ++++++++----
f92ce9
 ldap/servers/slapd/dse.c                           |  74 +++++++-------
f92ce9
 ldap/servers/slapd/plugin.c                        | 110 ++++++++++++---------
f92ce9
 ldap/servers/slapd/task.c                          |  10 +-
f92ce9
 9 files changed, 161 insertions(+), 122 deletions(-)
f92ce9
f92ce9
diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c
f92ce9
index c443a65..6a8fd22 100644
f92ce9
--- a/ldap/servers/plugins/automember/automember.c
f92ce9
+++ b/ldap/servers/plugins/automember/automember.c
f92ce9
@@ -406,7 +406,6 @@ automember_close(Slapi_PBlock * pb)
f92ce9
             automember_task_add_map_entries);
f92ce9
 
f92ce9
     automember_delete_config();
f92ce9
-    slapi_ch_free((void **)&g_automember_config);
f92ce9
     slapi_sdn_free(&_PluginDN);
f92ce9
     slapi_sdn_free(&_ConfigAreaDN);
f92ce9
     slapi_destroy_rwlock(g_automember_config_lock);
f92ce9
@@ -449,6 +448,8 @@ automember_load_config()
f92ce9
     /* Clear out any old config. */
f92ce9
     automember_config_write_lock();
f92ce9
     automember_delete_config();
f92ce9
+    g_automember_config = (PRCList *)slapi_ch_calloc(1, sizeof(struct configEntry));
f92ce9
+    PR_INIT_CLIST(g_automember_config);
f92ce9
 
f92ce9
     search_pb = slapi_pblock_new();
f92ce9
 
f92ce9
@@ -866,6 +867,7 @@ automember_delete_config()
f92ce9
         list = PR_LIST_HEAD(g_automember_config);
f92ce9
         automember_delete_configEntry(list);
f92ce9
     }
f92ce9
+    slapi_ch_free((void **)&g_automember_config);
f92ce9
 
f92ce9
     return;
f92ce9
 }
f92ce9
diff --git a/ldap/servers/plugins/dna/dna.c b/ldap/servers/plugins/dna/dna.c
f92ce9
index 75edca8..ded0bbb 100644
f92ce9
--- a/ldap/servers/plugins/dna/dna.c
f92ce9
+++ b/ldap/servers/plugins/dna/dna.c
f92ce9
@@ -202,6 +202,7 @@ static char *hostname = NULL;
f92ce9
 static char *portnum = NULL;
f92ce9
 static char *secureportnum = NULL;
f92ce9
 
f92ce9
+static Slapi_Eq_Context eq_ctx = {0};
f92ce9
 
f92ce9
 /**
f92ce9
  * server struct for shared ranges
f92ce9
@@ -708,6 +709,7 @@ dna_close(Slapi_PBlock * pb)
f92ce9
     slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
f92ce9
                     "--> dna_close\n");
f92ce9
 
f92ce9
+    slapi_eq_cancel(eq_ctx);
f92ce9
     dna_delete_config(NULL);
f92ce9
     slapi_ch_free((void **)&dna_global_config);
f92ce9
     slapi_destroy_rwlock(g_dna_cache_lock);
f92ce9
@@ -869,7 +871,7 @@ dna_load_plugin_config(Slapi_PBlock *pb, int use_eventq)
f92ce9
          * starting up  would cause the change to not
f92ce9
          * get changelogged. */
f92ce9
         time(&now;;
f92ce9
-        slapi_eq_once(dna_update_config_event, NULL, now + 30);
f92ce9
+        eq_ctx = slapi_eq_once(dna_update_config_event, NULL, now + 30);
f92ce9
     } else {
f92ce9
         dna_update_config_event(0, NULL);
f92ce9
     }
f92ce9
@@ -2404,7 +2406,7 @@ static int dna_get_next_value(struct configEntry *config_entry,
f92ce9
         } else {
f92ce9
             /* dna_first_free_value() failed for some unknown reason */
f92ce9
             slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
f92ce9
-                            "dna_get_next_value: failed to allocate a new ID!!\n");
f92ce9
+                            "dna_get_next_value: failed to allocate a new ID!! (set(%d) (max: %d)\n",setval,config_entry->maxval);
f92ce9
             goto done;
f92ce9
         }
f92ce9
     }
f92ce9
@@ -3401,7 +3403,7 @@ _dna_pre_op_add(Slapi_PBlock *pb, Slapi_Entry *e, char **errstr)
f92ce9
                         ret = dna_first_free_value(config_entry, &setval);
f92ce9
                         if (LDAP_SUCCESS != ret){
f92ce9
                             slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
f92ce9
-                                            "dna_pre_op: failed to allocate a new ID\n");
f92ce9
+                                            "dna_pre_op: failed to allocate a new ID 1\n");
f92ce9
                             /* Set an error string to be returned to the client. */
f92ce9
                             *errstr = slapi_ch_smprintf("Allocation of a new value for range"
f92ce9
                                                " %s failed! Unable to proceed.",
f92ce9
@@ -3412,7 +3414,9 @@ _dna_pre_op_add(Slapi_PBlock *pb, Slapi_Entry *e, char **errstr)
f92ce9
                     } else {
f92ce9
                         /* dna_first_free_value() failed for some unknown reason */
f92ce9
                         slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
f92ce9
-                                        "dna_pre_op: failed to allocate a new ID!!\n");
f92ce9
+                                        "dna_pre_op: failed to allocate a new ID!! 2\n");
f92ce9
+                        slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
f92ce9
+                                                    "dna_get_next_value: failed to allocate a new ID!! (set(%d) (max: %d)\n",setval,config_entry->maxval);
f92ce9
                         /* Set an error string to be returned to the client. */
f92ce9
                         *errstr = slapi_ch_smprintf("Allocation of a new value for range"
f92ce9
                                                " %s failed! Unable to proceed.",
f92ce9
@@ -3678,6 +3682,8 @@ _dna_pre_op_modify(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Mods *smods, char **e
f92ce9
                         /* dna_first_free_value() failed for some unknown reason */
f92ce9
                         slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
f92ce9
                                         "dna_pre_op: failed to allocate a new ID!!\n");
f92ce9
+                        slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
f92ce9
+                                                    "dna_get_next_value: failed to allocate a new ID!! (set(%d) (max: %d)\n",setval,config_entry->maxval);
f92ce9
                         /* Set an error string to be returned to the client. */
f92ce9
                         *errstr = slapi_ch_smprintf("Allocation of a new value for range"
f92ce9
                                            " %s failed! Unable to proceed.",
f92ce9
diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
f92ce9
index cb4ef75..bfa733a 100644
f92ce9
--- a/ldap/servers/plugins/memberof/memberof.c
f92ce9
+++ b/ldap/servers/plugins/memberof/memberof.c
f92ce9
@@ -2764,7 +2764,7 @@ int memberof_task_add(Slapi_PBlock *pb, Slapi_Entry *e,
f92ce9
 	mytaskdata->bind_dn = slapi_ch_strdup(bind_dn);
f92ce9
 
f92ce9
 	/* allocate new task now */
f92ce9
-	task = slapi_plugin_new_task(slapi_entry_get_ndn(e), pb);
f92ce9
+	task = slapi_plugin_new_task(slapi_entry_get_ndn(e), arg);
f92ce9
 
f92ce9
 	/* register our destructor for cleaning up our private data */
f92ce9
 	slapi_task_set_destructor_fn(task, memberof_task_destructor);
f92ce9
diff --git a/ldap/servers/plugins/rootdn_access/rootdn_access.c b/ldap/servers/plugins/rootdn_access/rootdn_access.c
f92ce9
index 9122f9b..3045e9f 100644
f92ce9
--- a/ldap/servers/plugins/rootdn_access/rootdn_access.c
f92ce9
+++ b/ldap/servers/plugins/rootdn_access/rootdn_access.c
f92ce9
@@ -217,7 +217,7 @@ rootdn_close(Slapi_PBlock *pb)
f92ce9
     slapi_ch_array_free(hosts);
f92ce9
     slapi_ch_array_free(hosts_to_deny);
f92ce9
     slapi_ch_array_free(ips);
f92ce9
-    slapi_ch_array_free(ips);
f92ce9
+    slapi_ch_array_free(ips_to_deny);
f92ce9
 
f92ce9
     return 0;
f92ce9
 }
f92ce9
@@ -416,6 +416,8 @@ rootdn_load_config(Slapi_PBlock *pb)
f92ce9
         }
f92ce9
     } else {
f92ce9
         /* failed to get the plugin entry */
f92ce9
+        slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_load_config: "
f92ce9
+                "Failed to get plugin entry\n");
f92ce9
         result = -1;
f92ce9
     }
f92ce9
 
f92ce9
diff --git a/ldap/servers/plugins/schema_reload/schema_reload.c b/ldap/servers/plugins/schema_reload/schema_reload.c
f92ce9
index 3ff4c4d..b1a5bb8 100644
f92ce9
--- a/ldap/servers/plugins/schema_reload/schema_reload.c
f92ce9
+++ b/ldap/servers/plugins/schema_reload/schema_reload.c
f92ce9
@@ -273,7 +273,7 @@ schemareload_add(Slapi_PBlock *pb, Slapi_Entry *e,
f92ce9
     schemadir = fetch_attr(e, "schemadir", NULL);
f92ce9
 
f92ce9
     /* allocate new task now */
f92ce9
-    task = slapi_plugin_new_task(slapi_entry_get_ndn(e), pb);
f92ce9
+    task = slapi_plugin_new_task(slapi_entry_get_ndn(e), arg);
f92ce9
     if (task == NULL) {
f92ce9
         slapi_log_error(SLAPI_LOG_FATAL, "schemareload", "unable to allocate new task!\n");
f92ce9
         *returncode = LDAP_OPERATIONS_ERROR;
f92ce9
diff --git a/ldap/servers/plugins/uiduniq/uid.c b/ldap/servers/plugins/uiduniq/uid.c
f92ce9
index 07ff0ec..f37ab8c 100644
f92ce9
--- a/ldap/servers/plugins/uiduniq/uid.c
f92ce9
+++ b/ldap/servers/plugins/uiduniq/uid.c
f92ce9
@@ -1265,6 +1265,38 @@ preop_modrdn(Slapi_PBlock *pb)
f92ce9
 
f92ce9
 }
f92ce9
 
f92ce9
+static int
f92ce9
+uiduniq_start(Slapi_PBlock *pb)
f92ce9
+{
f92ce9
+    Slapi_Entry *plugin_entry = NULL;
f92ce9
+    struct attr_uniqueness_config *config = NULL;
f92ce9
+
f92ce9
+    if (slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &plugin_entry) == 0){
f92ce9
+        /* load the config into the config list */
f92ce9
+        if ((config = uniqueness_entry_to_config(pb, plugin_entry)) == NULL) {
f92ce9
+            return SLAPI_PLUGIN_FAILURE;
f92ce9
+        }
f92ce9
+        slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, (void*) config);
f92ce9
+    }
f92ce9
+
f92ce9
+    return 0;
f92ce9
+}
f92ce9
+
f92ce9
+static int
f92ce9
+uiduniq_close(Slapi_PBlock *pb)
f92ce9
+{
f92ce9
+    Slapi_Entry *plugin_entry = NULL;
f92ce9
+    struct attr_uniqueness_config *config = NULL;
f92ce9
+
f92ce9
+    slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &config);
f92ce9
+    if (config) {
f92ce9
+            slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, NULL);
f92ce9
+            free_uniqueness_config(config);
f92ce9
+            slapi_ch_free((void **) &config);
f92ce9
+    }
f92ce9
+    return 0;
f92ce9
+}
f92ce9
+
f92ce9
 /* ------------------------------------------------------------ */
f92ce9
 /*
f92ce9
  * Initialize the plugin
f92ce9
@@ -1307,13 +1339,6 @@ NSUniqueAttr_Init(Slapi_PBlock *pb)
f92ce9
     }
f92ce9
     slapi_ch_free_string(&plugin_type);
f92ce9
 
f92ce9
-    /* load the config into the config list */
f92ce9
-    if ((config = uniqueness_entry_to_config(pb, plugin_entry)) == NULL) {
f92ce9
-            err = SLAPI_PLUGIN_FAILURE;
f92ce9
-            break;
f92ce9
-    }
f92ce9
-    slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, (void*) config);
f92ce9
-
f92ce9
     /* Provide descriptive information */
f92ce9
     err = slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
f92ce9
             (void*)&pluginDesc);
f92ce9
@@ -1329,30 +1354,26 @@ NSUniqueAttr_Init(Slapi_PBlock *pb)
f92ce9
     err = slapi_pblock_set(pb, premdn, (void*)preop_modrdn);
f92ce9
     if (err) break;
f92ce9
 
f92ce9
+    err = slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN, (void *) uiduniq_start);
f92ce9
+    if (err) break;
f92ce9
+
f92ce9
+    err = slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN, (void *) uiduniq_close);
f92ce9
+    if (err) break;
f92ce9
+
f92ce9
+
f92ce9
   END
f92ce9
 
f92ce9
   if (err) {
f92ce9
-    slapi_log_error(SLAPI_LOG_PLUGIN, "NSUniqueAttr_Init",
f92ce9
-             "Error: %d\n", err);
f92ce9
-    if (config) {
f92ce9
-            slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, NULL);
f92ce9
-            free_uniqueness_config(config);
f92ce9
-            slapi_ch_free((void **) &config);
f92ce9
-    }
f92ce9
+    slapi_log_error(SLAPI_LOG_PLUGIN, "NSUniqueAttr_Init", "Error: %d\n", err);
f92ce9
     err = -1;
f92ce9
   }
f92ce9
   else
f92ce9
-    slapi_log_error(SLAPI_LOG_PLUGIN, "NSUniqueAttr_Init",
f92ce9
-             "plugin loaded\n");
f92ce9
+    slapi_log_error(SLAPI_LOG_PLUGIN, "NSUniqueAttr_Init", "plugin loaded\n");
f92ce9
 
f92ce9
   return err;
f92ce9
 }
f92ce9
 
f92ce9
-int
f92ce9
-uidunique_init(Slapi_PBlock *pb)
f92ce9
-{
f92ce9
-  return NSUniqueAttr_Init(pb);
f92ce9
-}
f92ce9
+
f92ce9
 
f92ce9
 
f92ce9
 /* ------------------------------------------------------------ */
f92ce9
diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
f92ce9
index fc5f492..f0ce255 100644
f92ce9
--- a/ldap/servers/slapd/dse.c
f92ce9
+++ b/ldap/servers/slapd/dse.c
f92ce9
@@ -1827,6 +1827,7 @@ dse_modify(Slapi_PBlock *pb) /* JCM There should only be one exit point from thi
f92ce9
     int retval = -1;
f92ce9
     int need_be_postop = 0;
f92ce9
     int plugin_started = 0;
f92ce9
+    int internal_op = 0;
f92ce9
 
f92ce9
     PR_ASSERT(pb);
f92ce9
     if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &pdse ) < 0 ||
f92ce9
@@ -1843,6 +1844,8 @@ dse_modify(Slapi_PBlock *pb) /* JCM There should only be one exit point from thi
f92ce9
         return retval;
f92ce9
     }
f92ce9
 
f92ce9
+    internal_op = operation_is_flag_set(pb->pb_op, OP_FLAG_INTERNAL);
f92ce9
+
f92ce9
     /* Find the entry we are about to modify. */
f92ce9
     ec = dse_get_entry_copy(pdse, sdn, DSE_USE_LOCK);
f92ce9
     if ( ec == NULL ) {
f92ce9
@@ -2039,20 +2042,22 @@ dse_modify(Slapi_PBlock *pb) /* JCM There should only be one exit point from thi
f92ce9
         }
f92ce9
     }
f92ce9
     /*
f92ce9
-     * Perform postop plugin configuration changes
f92ce9
+     * Perform postop plugin configuration changes unless this is an internal operation
f92ce9
      */
f92ce9
-    if(returncode == LDAP_SUCCESS){
f92ce9
-        dse_post_modify_plugin(ec, ecc, mods);
f92ce9
-    } else if(plugin_started){
f92ce9
-        if(plugin_started == 1){
f92ce9
-        	/* the op failed, turn the plugin off */
f92ce9
-            plugin_delete(ecc, returntext, 0 /* not locked */);
f92ce9
-        } else if (plugin_started == 2){
f92ce9
-            /*
f92ce9
-             * This probably can't happen, but...
f92ce9
-             * the op failed, turn the plugin back on.
f92ce9
-             */
f92ce9
-            plugin_add(ecc, returntext, 0 /* not locked */);
f92ce9
+    if(!internal_op){
f92ce9
+        if(returncode == LDAP_SUCCESS){
f92ce9
+            dse_post_modify_plugin(ec, ecc, mods);
f92ce9
+        } else if(plugin_started){
f92ce9
+            if(plugin_started == 1){
f92ce9
+                /* the op failed, turn the plugin off */
f92ce9
+                plugin_delete(ecc, returntext, 0 /* not locked */);
f92ce9
+            } else if (plugin_started == 2){
f92ce9
+                /*
f92ce9
+                 * This probably can't happen, but...
f92ce9
+                 * the op failed, turn the plugin back on.
f92ce9
+                 */
f92ce9
+                plugin_add(ecc, returntext, 0 /* not locked */);
f92ce9
+            }
f92ce9
         }
f92ce9
     }
f92ce9
 
f92ce9
@@ -2065,6 +2070,7 @@ static void
f92ce9
 dse_post_modify_plugin(Slapi_Entry *entryBefore, Slapi_Entry *entryAfter, LDAPMod **mods)
f92ce9
 {
f92ce9
     char *enabled = NULL;
f92ce9
+    int restart_plugin = 1;
f92ce9
     int i;
f92ce9
 
f92ce9
     if (!slapi_entry_attr_hasvalue(entryBefore, SLAPI_ATTR_OBJECTCLASS, "nsSlapdPlugin") ||
f92ce9
@@ -2080,31 +2086,18 @@ dse_post_modify_plugin(Slapi_Entry *entryBefore, Slapi_Entry *entryAfter, LDAPMo
f92ce9
          !strcasecmp(enabled, "on"))
f92ce9
     {
f92ce9
         for(i = 0; mods && mods[i]; i++){
f92ce9
-            /* Check if we are modifying a plugin's config, if so restart the plugin */
f92ce9
-            if (strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_PATH) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_INITFN) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_TYPE) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_DEPENDS_ON_TYPE) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_DEPENDS_ON_NAMED) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_SCHEMA_CHECK) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_BE_TXN) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_TARGET_SUBTREE) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_EXCLUDE_TARGET_SUBTREE) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_BIND_SUBTREE) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_EXCLUDE_BIND_SUBTREE) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_LOAD_NOW) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_LOAD_GLOBAL) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_PRECEDENCE) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_LOG_ACCESS) == 0 ||
f92ce9
-                strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_LOG_AUDIT) == 0 )
f92ce9
-            {
f92ce9
-                /* for all other plugin config changes, restart the plugin */
f92ce9
-                if(plugin_restart(entryBefore, entryAfter) != LDAP_SUCCESS){
f92ce9
-                    slapi_log_error(SLAPI_LOG_FATAL,"dse_post_modify_plugin", "The configuration change "
f92ce9
-                            "for plugin (%s) could not be applied dynamically, and will be ignored until "
f92ce9
-                            "the server is restarted.\n",
f92ce9
-                            slapi_entry_get_dn(entryBefore));
f92ce9
-                }
f92ce9
+            if (strcasecmp(mods[i]->mod_type, ATTR_PLUGIN_ENABLED) == 0){
f92ce9
+                /* we already stop/started the pugin - don't do it again */
f92ce9
+                restart_plugin = 0;
f92ce9
+                break;
f92ce9
+            }
f92ce9
+        }
f92ce9
+        if(restart_plugin){       /* for all other plugin config changes, restart the plugin */
f92ce9
+            if(plugin_restart(entryBefore, entryAfter) != LDAP_SUCCESS){
f92ce9
+                slapi_log_error(SLAPI_LOG_FATAL,"dse_post_modify_plugin", "The configuration change "
f92ce9
+                        "for plugin (%s) could not be applied dynamically, and will be ignored until "
f92ce9
+                        "the server is restarted.\n",
f92ce9
+                        slapi_entry_get_dn(entryBefore));
f92ce9
             }
f92ce9
         }
f92ce9
     }
f92ce9
@@ -2690,7 +2683,10 @@ slapi_config_register_callback_plugin(int operation,
f92ce9
             Slapi_DN dn;
f92ce9
 
f92ce9
             slapi_sdn_init_dn_byref(&dn,base);
f92ce9
-            rc = (NULL != dse_register_callback(pdse, operation, flags, &dn, scope, filter, fn, fn_arg, pb ? pb->pb_plugin: NULL));
f92ce9
+            /* if a pblock was passed, this is a plugin, so set the f_arg as the plugin */
f92ce9
+            rc = (NULL != dse_register_callback(pdse, operation, flags, &dn, scope, filter, fn,
f92ce9
+                                                pb ? (void*)pb->pb_plugin : fn_arg,
f92ce9
+                                                pb ? pb->pb_plugin: NULL));
f92ce9
             slapi_sdn_done(&dn;;
f92ce9
         }
f92ce9
     }
f92ce9
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
f92ce9
index dde3ce5..820c25f 100644
f92ce9
--- a/ldap/servers/slapd/plugin.c
f92ce9
+++ b/ldap/servers/slapd/plugin.c
f92ce9
@@ -58,6 +58,11 @@
f92ce9
 #define CHECK_ALL 0
f92ce9
 #define CHECK_TYPE 1
f92ce9
 
f92ce9
+/* plugin removal flags */
f92ce9
+#define PLUGIN_NOT_FOUND 0
f92ce9
+#define PLUGIN_REMOVED 1
f92ce9
+#define PLUGIN_BUSY 2
f92ce9
+
f92ce9
 static char *critical_plugins[] = { "cn=ldbm database,cn=plugins,cn=config",
f92ce9
                                     "cn=ACL Plugin,cn=plugins,cn=config",
f92ce9
                                     "cn=ACL preoperation,cn=plugins,cn=config",
f92ce9
@@ -3294,7 +3299,7 @@ plugin_remove_plugins(struct slapdplugin *plugin_entry, char *plugin_type)
f92ce9
     struct slapdplugin *plugin = NULL;
f92ce9
     struct slapdplugin *plugin_next = NULL;
f92ce9
     struct slapdplugin *plugin_prev = NULL;
f92ce9
-    int removed = 0;
f92ce9
+    int removed = PLUGIN_NOT_FOUND;
f92ce9
     int type;
f92ce9
 
f92ce9
     /* look everywhere for other plugin functions with the plugin id */
f92ce9
@@ -3315,7 +3320,13 @@ plugin_remove_plugins(struct slapdplugin *plugin_entry, char *plugin_type)
f92ce9
 
f92ce9
                 pblock_init(&pb;;
f92ce9
                 plugin_set_stopped(plugin);
f92ce9
-                plugin_op_all_finished(plugin);
f92ce9
+                if (slapi_counter_get_value(plugin->plg_op_counter) > 0){
f92ce9
+                    /*
f92ce9
+                     * Plugin is still busy, and we might be blocking it
f92ce9
+                     * by holding global plugin lock so return for now.
f92ce9
+                     */
f92ce9
+                    return PLUGIN_BUSY;
f92ce9
+                }
f92ce9
                 plugin_call_one( plugin, SLAPI_PLUGIN_CLOSE_FN, &pb;;
f92ce9
 
f92ce9
                 if(plugin_prev){
f92ce9
@@ -3332,7 +3343,7 @@ plugin_remove_plugins(struct slapdplugin *plugin_entry, char *plugin_type)
f92ce9
                 plugin_remove_from_shutdown(plugin);
f92ce9
                 plugin->plg_removed = 1;
f92ce9
                 plugin->plg_started = 0;
f92ce9
-                removed = 1;
f92ce9
+                removed = PLUGIN_REMOVED;
f92ce9
             } else {
f92ce9
                 plugin_prev = plugin;
f92ce9
             }
f92ce9
@@ -3362,15 +3373,10 @@ plugin_delete(Slapi_Entry *plugin_entry, char *returntext, int locked)
f92ce9
     const char *plugin_dn = slapi_entry_get_dn_const(plugin_entry);
f92ce9
     char *value = NULL;
f92ce9
     int td_locked = 1;
f92ce9
-    int removed = 0;
f92ce9
+    int removed = PLUGIN_BUSY;
f92ce9
     int type = 0;
f92ce9
     int rc = LDAP_SUCCESS;
f92ce9
 
f92ce9
-    if(!locked){
f92ce9
-        slapi_rwlock_wrlock(global_rwlock);
f92ce9
-    }
f92ce9
-    slapi_td_set_plugin_locked(&td_locked);
f92ce9
-
f92ce9
     /* Critical server plugins can not be disabled */
f92ce9
     if(plugin_is_critical(plugin_entry)){
f92ce9
         LDAPDebug(LDAP_DEBUG_ANY, "plugin_delete: plugin \"%s\" is critical to server operations, and can not be disabled\n",
f92ce9
@@ -3390,54 +3396,62 @@ plugin_delete(Slapi_Entry *plugin_entry, char *returntext, int locked)
f92ce9
         rc = -1;
f92ce9
         goto done;
f92ce9
     } else {
f92ce9
-        rc = plugin_get_type_and_list(value, &type, &plugin_list);
f92ce9
-        if ( rc != 0 ) {
f92ce9
-            /* error: unknown plugin type */
f92ce9
-            LDAPDebug(LDAP_DEBUG_ANY, "plugin_delete: unknown plugin type \"%s\" in entry \"%s\"\n",
f92ce9
-                      value, slapi_entry_get_dn_const(plugin_entry), 0);
f92ce9
-            PR_snprintf (returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Plugin delete failed: unknown plugin type "
f92ce9
+        while(removed == PLUGIN_BUSY){
f92ce9
+            removed = PLUGIN_NOT_FOUND;
f92ce9
+            if(!locked){
f92ce9
+                slapi_rwlock_wrlock(global_rwlock);
f92ce9
+            }
f92ce9
+            slapi_td_set_plugin_locked(&td_locked);
f92ce9
+
f92ce9
+            rc = plugin_get_type_and_list(value, &type, &plugin_list);
f92ce9
+            if ( rc != 0 ) {
f92ce9
+                /* error: unknown plugin type */
f92ce9
+                LDAPDebug(LDAP_DEBUG_ANY, "plugin_delete: unknown plugin type \"%s\" in entry \"%s\"\n",
f92ce9
+                          value, slapi_entry_get_dn_const(plugin_entry), 0);
f92ce9
+                PR_snprintf (returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Plugin delete failed: unknown plugin type "
f92ce9
                          "\"%s\" in entry.",value);
f92ce9
-            rc = -1;
f92ce9
-            goto done;
f92ce9
-        }
f92ce9
+                rc = -1;
f92ce9
+                goto unlock;
f92ce9
+            }
f92ce9
 
f92ce9
-        /*
f92ce9
-         * Skip syntax/matching rule/database plugins - these can not be disabled as it
f92ce9
-         * could break existing schema.  We allow the update to occur, but it will
f92ce9
-         * not take effect until the next server restart.
f92ce9
-         */
f92ce9
-        if(type == SLAPI_PLUGIN_SYNTAX || type == SLAPI_PLUGIN_MATCHINGRULE || type == SLAPI_PLUGIN_DATABASE){
f92ce9
-            removed = 1;  /* avoids error check below */
f92ce9
-            goto done;
f92ce9
-        }
f92ce9
+            /*
f92ce9
+             * Skip syntax/matching rule/database plugins - these can not be disabled as it
f92ce9
+             * could break existing schema.  We allow the update to occur, but it will
f92ce9
+             * not take effect until the next server restart.
f92ce9
+             */
f92ce9
+            if(type == SLAPI_PLUGIN_SYNTAX || type == SLAPI_PLUGIN_MATCHINGRULE || type == SLAPI_PLUGIN_DATABASE){
f92ce9
+                removed = PLUGIN_REMOVED;  /* avoids error check below */
f92ce9
+                goto unlock;
f92ce9
+            }
f92ce9
 
f92ce9
-        /*
f92ce9
-         * Now remove the plugin from the list and the hashtable
f92ce9
-         */
f92ce9
-        for(plugin = *plugin_list; plugin ; plugin = plugin->plg_next){
f92ce9
-            if(strcasecmp(plugin->plg_dn, plugin_dn) == 0){
f92ce9
-                /*
f92ce9
-                 * Make sure there are no other plugins that depend on this one before removing it
f92ce9
-                 */
f92ce9
-                if(plugin_delete_check_dependency(plugin, CHECK_ALL, returntext) != LDAP_SUCCESS){
f92ce9
-                    LDAPDebug(LDAP_DEBUG_ANY, "plugin_delete: failed to disable/delete plugin (%s)\n",
f92ce9
-                              plugin->plg_dn,0,0);
f92ce9
-                    rc = -1;
f92ce9
-                    goto done;
f92ce9
+            /*
f92ce9
+             * Now remove the plugin from the list and the hashtable
f92ce9
+             */
f92ce9
+            for(plugin = *plugin_list; plugin ; plugin = plugin->plg_next){
f92ce9
+                if(strcasecmp(plugin->plg_dn, plugin_dn) == 0){
f92ce9
+                    /*
f92ce9
+                     * Make sure there are no other plugins that depend on this one before removing it
f92ce9
+                     */
f92ce9
+                    if(plugin_delete_check_dependency(plugin, CHECK_ALL, returntext) != LDAP_SUCCESS){
f92ce9
+                        LDAPDebug(LDAP_DEBUG_ANY, "plugin_delete: failed to disable/delete plugin (%s)\n",
f92ce9
+                                  plugin->plg_dn,0,0);
f92ce9
+                        rc = -1;
f92ce9
+                        break;
f92ce9
+                    }
f92ce9
+                    removed = plugin_remove_plugins(plugin, value);
f92ce9
+                    break;
f92ce9
                 }
f92ce9
-                removed = plugin_remove_plugins(plugin, value);
f92ce9
-                break;
f92ce9
             }
f92ce9
+unlock:
f92ce9
+            if(!locked){
f92ce9
+                slapi_rwlock_unlock(global_rwlock);
f92ce9
+            }
f92ce9
+            td_locked = 0;
f92ce9
+            slapi_td_set_plugin_locked(&td_locked);
f92ce9
         }
f92ce9
     }
f92ce9
 
f92ce9
 done:
f92ce9
-    if(!locked){
f92ce9
-        slapi_rwlock_unlock(global_rwlock);
f92ce9
-    }
f92ce9
-    td_locked = 0;
f92ce9
-    slapi_td_set_plugin_locked(&td_locked);
f92ce9
-
f92ce9
     slapi_ch_free_string(&value);
f92ce9
 
f92ce9
     if(!removed && rc == 0){
f92ce9
diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
f92ce9
index b1f7652..98ec88c 100644
f92ce9
--- a/ldap/servers/slapd/task.c
f92ce9
+++ b/ldap/servers/slapd/task.c
f92ce9
@@ -131,9 +131,9 @@ slapi_new_task(const char *dn)
f92ce9
 }
f92ce9
 
f92ce9
 Slapi_Task *
f92ce9
-slapi_plugin_new_task(const char *dn, void *plugin_pb)
f92ce9
+slapi_plugin_new_task(const char *dn, void *plugin)
f92ce9
 {
f92ce9
-    return new_task(dn, plugin_pb);
f92ce9
+    return new_task(dn, plugin);
f92ce9
 }
f92ce9
 
f92ce9
 /* slapi_destroy_task: destroy a task
f92ce9
@@ -540,7 +540,7 @@ slapi_plugin_task_register_handler(const char *name, dseCallbackFn func, Slapi_P
f92ce9
 
f92ce9
     /* register add callback */
f92ce9
     slapi_config_register_callback_plugin(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP,
f92ce9
-                                   dn, LDAP_SCOPE_SUBTREE, "(objectclass=*)", func, NULL, plugin_pb);
f92ce9
+                                   dn, LDAP_SCOPE_SUBTREE, "(objectclass=*)", func, plugin_pb, plugin_pb);
f92ce9
     /* deny modify/delete of the root task entry */
f92ce9
     slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP,
f92ce9
                                    dn, LDAP_SCOPE_BASE, "(objectclass=*)", task_deny, NULL);
f92ce9
@@ -583,11 +583,9 @@ void slapi_task_set_cancel_fn(Slapi_Task *task, TaskCallbackFn func)
f92ce9
  ***********************************/
f92ce9
 /* create a new task, fill in DN, and setup modify callback */
f92ce9
 static Slapi_Task *
f92ce9
-new_task(const char *rawdn, void *plugin_pb)
f92ce9
+new_task(const char *rawdn, void *plugin)
f92ce9
 {
f92ce9
     Slapi_Task *task = NULL;
f92ce9
-    Slapi_PBlock *pb = (Slapi_PBlock *)plugin_pb;
f92ce9
-    void *plugin = pb ? pb->pb_plugin : NULL;
f92ce9
     char *dn = NULL;
f92ce9
 
f92ce9
     if (rawdn == NULL) {
f92ce9
-- 
f92ce9
1.9.3
f92ce9