[Asterisk-code-review] RFC: Add support for disabled modules. (asterisk[master])

Corey Farrell asteriskteam at digium.com
Tue Oct 2 13:43:43 CDT 2018


Corey Farrell has uploaded this change for review. ( https://gerrit.asterisk.org/10377


Change subject: RFC: Add support for disabled modules.
......................................................................

RFC: Add support for disabled modules.

Change-Id: Ic44810ca6ce3deca30bceeb4eaa306d94f6b90e8
---
M include/asterisk/module.h
M main/loader.c
M res/res_statsd.c
3 files changed, 121 insertions(+), 18 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/77/10377/1

diff --git a/include/asterisk/module.h b/include/asterisk/module.h
index 08b4c43..4c3c68a 100644
--- a/include/asterisk/module.h
+++ b/include/asterisk/module.h
@@ -66,11 +66,49 @@
 };
 
 enum ast_module_load_result {
-	AST_MODULE_LOAD_SUCCESS = 0,    /*!< Module loaded and configured */
-	AST_MODULE_LOAD_DECLINE = 1,    /*!< Module is not configured */
-	AST_MODULE_LOAD_SKIP = 2,       /*!< Module was skipped for some reason (For loader.c use only. Should never be returned by modules)*/
-	AST_MODULE_LOAD_PRIORITY = 3,   /*!< Module is not loaded yet, but is added to priority list */
-	AST_MODULE_LOAD_FAILURE = -1,   /*!< Module could not be loaded properly */
+	/*! Module is loaded and configured. */
+	AST_MODULE_LOAD_SUCCESS = 0,
+	/*!
+	 * \brief Module has failed to load, may be in an inconsistent state.
+	 *
+	 * This value is used when a module fails to start but does not risk
+	 * system-wide stability.  Declined modules will prevent other any
+	 * dependent module from starting.
+	 */
+	AST_MODULE_LOAD_DECLINE = 1,
+	/*! \internal
+	 * \brief Module was skipped for some reason.
+	 *
+	 * \note For loader.c use only. Should never be returned by modules.
+	 */
+	AST_MODULE_LOAD_SKIP = 2,
+	/*! \internal
+	 * \brief Module is not loaded yet, but is added to priority list.
+	 *
+	 * \note For loader.c use only. Should never be returned by modules.
+	 */
+	AST_MODULE_LOAD_PRIORITY = 3,
+	/*!
+	 * \brief Module load is successful but disabled.
+	 *
+	 * Returning this value has the same effect as calling
+	 * ast_module_set_disabled(1) then returning AST_MODULE_LOAD_SUCCESS.
+	 * It is important that a module not unload if returning LOAD_DISABLED.
+	 * load_module will not be called again.  It is expected that a disabled
+	 * module can be enabled by modifying and reload the module's configuration.
+	 *
+	 * See \ref ast_module_set_disabled
+	 */
+	AST_MODULE_LOAD_DISABLED = 4,
+	/*!
+	 * \brief Module could not be loaded properly.
+	 *
+	 * This return should only be returned by modules for unrecoverable
+	 * failures that cause the whole system to become unstable.  In almost
+	 * all cases \ref AST_MODULE_LOAD_DECLINE or \ref AST_MODULE_LOAD_DISABLED
+	 * should be used instead.
+	 */
+	AST_MODULE_LOAD_FAILURE = -1,
 };
 
 /*!
@@ -136,6 +174,25 @@
 int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode);
 
 /*!
+ * \brief Flag a module as disabled.
+ * \param mod Module to flag
+ * \param disabled Zero to clear the flag, non-zero to set.
+ *
+ * \retval 0 Module was not previously disabled
+ * \retval 1 Module was previously disabled
+ */
+int ast_module_set_disabled(struct ast_module *mod, int disabled);
+
+/*!
+ * \brief Retrieve the status of a module.
+ *
+ * \param mod Module to check.
+ *
+ * \returns A string representing the current status of \a mod.
+ */
+const char *ast_module_status(const struct ast_module *mod);
+
+/*!
  * \brief Reload asterisk modules.
  * \param name the name of the module to reload
  *
diff --git a/main/loader.c b/main/loader.c
index eb345b5..8291a7c 100644
--- a/main/loader.c
+++ b/main/loader.c
@@ -177,6 +177,8 @@
 		unsigned int running:1;
 		/*! The module has declined to start. */
 		unsigned int declined:1;
+		/*! This module is disabled. */
+		unsigned int disabled:1;
 		/*! This module is being held open until it's time to shutdown. */
 		unsigned int keepuntilshutdown:1;
 		/*! The module is built-in. */
@@ -1048,8 +1050,9 @@
 		}
 	}
 
-	if (!error)
-		mod->flags.running = mod->flags.declined = 0;
+	if (!error) {
+		mod->flags.running = mod->flags.declined = mod->flags.disabled = 0;
+	}
 
 	AST_DLLIST_UNLOCK(&module_list);
 
@@ -1326,6 +1329,27 @@
 	publish_load_message_type("Reload", S_OR(name, "All"), res_buffer);
 }
 
+int ast_module_set_disabled(struct ast_module *mod, int disabled)
+{
+	int oldValue;
+
+	/* Ensure all non-zero is always 1 for matching against previous value. */
+	disabled = disabled ? 1 : 0;
+
+	ast_mutex_lock(&reloadlock);
+	oldValue = mod->flags.disabled;
+	mod->flags.disabled = disabled;
+	ast_mutex_unlock(&reloadlock);
+
+	if (disabled != oldValue) {
+		ast_log(LOG_NOTICE, "%s %s.\n",
+			ast_module_name(mod),
+			disabled ? "disabled" : "enabled");
+	}
+
+	return oldValue;
+}
+
 enum ast_module_reload_result ast_module_reload(const char *name)
 {
 	struct ast_module *cur;
@@ -1473,9 +1497,17 @@
 	if (!ast_fully_booted) {
 		ast_verb(1, "Loading %s.\n", mod->resource);
 	}
+
+	/* This should normally be a NOOP unless a previous attempted
+	 * load set disabled but then returned AST_MODULE_LOAD_DECLINE. */
+	ast_module_set_disabled(mod, 0);
 	res = mod->info->load();
 
 	switch (res) {
+	case AST_MODULE_LOAD_DISABLED:
+		ast_module_set_disabled(mod, 1);
+		res = AST_MODULE_LOAD_SUCCESS;
+		/* fall-through */
 	case AST_MODULE_LOAD_SUCCESS:
 		if (!ast_fully_booted) {
 			ast_verb(2, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
@@ -1782,11 +1814,12 @@
 			lres = load_resource(order->resource, !lasttry, &module_priorities, order->required, order->preload);
 			ast_debug(3, "PASS %d: %-46s %d\n", attempt, order->resource, lres);
 			switch (lres) {
+			case AST_MODULE_LOAD_DISABLED:
 			case AST_MODULE_LOAD_SUCCESS:
 			case AST_MODULE_LOAD_SKIP:
-				/* We're supplying module_priorities so SUCCESS isn't possible but we
-				 * still have to test for it.  SKIP is only used when we try to start a
-				 * module that is missing dependencies. */
+				/* We're supplying module_priorities so SUCCESS and DISABLED aren't
+				 * possible but we still have to test for them.  SKIP is only used
+				 * when we try to start a module that is missing dependencies. */
 				break;
 			case AST_MODULE_LOAD_DECLINE:
 				break;
@@ -2073,6 +2106,19 @@
 	return 0;
 }
 
+const char *ast_module_status(const struct ast_module *mod)
+{
+	if (mod->flags.running) {
+		return mod->flags.disabled ? "Disabled" : "Running";
+	}
+
+	if (mod->flags.declined) {
+		return "Run Declined";
+	}
+
+	return "Not Running";
+}
+
 int ast_update_module_list(int (*modentry)(const char *module, const char *description,
                                            int usecnt, const char *status, const char *like,
 										   enum ast_module_support_level support_level),
@@ -2090,7 +2136,7 @@
 			struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
 
 			total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
-				cur->flags.running ? "Running" : "Not Running", like, cur->info->support_level);
+				ast_module_status(cur), like, cur->info->support_level);
 		}
 	}
 
@@ -2118,7 +2164,7 @@
 			struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
 
 			total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
-				cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data);
+				ast_module_status(cur), like, cur->info->support_level, data);
 		}
 	}
 
@@ -2147,7 +2193,7 @@
 			struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
 
 			conditions_met += modentry(cur->resource, cur->info->description, cur->usecount,
-				cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data,
+				ast_module_status(cur), like, cur->info->support_level, data,
 				condition);
 		}
 	}
diff --git a/res/res_statsd.c b/res/res_statsd.c
index 3e08152..c83a278 100644
--- a/res/res_statsd.c
+++ b/res/res_statsd.c
@@ -271,7 +271,7 @@
 CONFIG_INFO_STANDARD(cfg_info, confs, conf_alloc,
 		     .files = ACO_FILES(&conf_file));
 
-/*! \brief Helper function to check if module is enabled. */
+/*! \brief Helper function to check if module should be enabled. */
 static char is_enabled(void)
 {
 	RAII_VAR(struct conf *, cfg, ao2_global_obj_ref(confs), ao2_cleanup);
@@ -303,6 +303,7 @@
 	ast_debug(3, "  statsd server = %s.\n", server);
 	ast_debug(3, "  add newline = %s\n", AST_YESNO(cfg->global->add_newline));
 	ast_debug(3, "  prefix = %s\n", cfg->global->prefix);
+	ast_module_set_disabled(AST_MODULE_SELF, 0);
 
 	return 0;
 }
@@ -314,6 +315,7 @@
 		close(socket_fd);
 		socket_fd = -1;
 	}
+	ast_module_set_disabled(AST_MODULE_SELF, 1);
 }
 
 static int load_module(void)
@@ -340,8 +342,7 @@
 		CHARFLDSET(struct conf_global_options, prefix));
 
 	if (aco_process_config(&cfg_info, 0)) {
-		aco_info_destroy(&cfg_info);
-		return AST_MODULE_LOAD_DECLINE;
+		return AST_MODULE_LOAD_DISABLED;
 	}
 
 	if (!is_enabled()) {
@@ -349,8 +350,7 @@
 	}
 
 	if (statsd_init() != 0) {
-		aco_info_destroy(&cfg_info);
-		return AST_MODULE_LOAD_DECLINE;
+		return AST_MODULE_LOAD_DISABLED;
 	}
 
 	return AST_MODULE_LOAD_SUCCESS;

-- 
To view, visit https://gerrit.asterisk.org/10377
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic44810ca6ce3deca30bceeb4eaa306d94f6b90e8
Gerrit-Change-Number: 10377
Gerrit-PatchSet: 1
Gerrit-Owner: Corey Farrell <git at cfware.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20181002/e1a93e75/attachment-0001.html>


More information about the asterisk-code-review mailing list