diff --git a/include/asterisk/module.h b/include/asterisk/module.h
index d3b9ddc20964f85cdf136e29f8b0bf21e58aa849..103cd3053c30cc888dc1c77a542b0c32123f73e1 100644
--- a/include/asterisk/module.h
+++ b/include/asterisk/module.h
@@ -357,6 +357,7 @@ void __ast_module_user_hangup_all(struct ast_module *);
 #define ast_module_user_hangup_all() __ast_module_user_hangup_all(AST_MODULE_SELF)
 
 struct ast_module *__ast_module_ref(struct ast_module *mod, const char *file, int line, const char *func);
+struct ast_module *__ast_module_running_ref(struct ast_module *mod, const char *file, int line, const char *func);
 void __ast_module_shutdown_ref(struct ast_module *mod, const char *file, int line, const char *func);
 void __ast_module_unref(struct ast_module *mod, const char *file, int line, const char *func);
 
@@ -369,6 +370,20 @@ void __ast_module_unref(struct ast_module *mod, const char *file, int line, cons
  * from being unloaded.
  */
 #define ast_module_ref(mod)           __ast_module_ref(mod, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+/*!
+ * \brief Hold a reference to the module if it is running.
+ * \param mod Module to reference
+ * \retval mod if running
+ * \retval NULL if not running
+ *
+ * The returned pointer should be released with ast_module_unref.
+ *
+ * \note A module reference will prevent the module from being unloaded.
+ */
+#define ast_module_running_ref(mod) \
+	__ast_module_running_ref(mod, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
 /*!
  * \brief Prevent unload of the module before shutdown
  * \param mod Module to hold
diff --git a/main/app.c b/main/app.c
index 215ec04e8b2232786e19a1fb4561c23ca3099c97..2db9a8f5086039fcee559347fb274bae4f95ec08 100644
--- a/main/app.c
+++ b/main/app.c
@@ -386,6 +386,7 @@ int ast_app_run_macro(struct ast_channel *autoservice_chan, struct ast_channel *
 	return res;
 }
 
+/* BUGBUG this is not thread safe. */
 static const struct ast_app_stack_funcs *app_stack_callbacks;
 
 void ast_install_stack_functions(const struct ast_app_stack_funcs *funcs)
@@ -399,16 +400,16 @@ const char *ast_app_expand_sub_args(struct ast_channel *chan, const char *args)
 	const char *new_args;
 
 	funcs = app_stack_callbacks;
-	if (!funcs || !funcs->expand_sub_args) {
+	if (!funcs || !funcs->expand_sub_args || !ast_module_running_ref(funcs->module)) {
 		ast_log(LOG_WARNING,
 			"Cannot expand 'Gosub(%s)' arguments.  The app_stack module is not available.\n",
 			args);
 		return NULL;
 	}
-	ast_module_ref(funcs->module);
 
 	new_args = funcs->expand_sub_args(chan, args);
 	ast_module_unref(funcs->module);
+
 	return new_args;
 }
 
@@ -418,13 +419,12 @@ int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *s
 	int res;
 
 	funcs = app_stack_callbacks;
-	if (!funcs || !funcs->run_sub) {
+	if (!funcs || !funcs->run_sub || !ast_module_running_ref(funcs->module)) {
 		ast_log(LOG_WARNING,
 			"Cannot run 'Gosub(%s)'.  The app_stack module is not available.\n",
 			sub_args);
 		return -1;
 	}
-	ast_module_ref(funcs->module);
 
 	if (autoservice_chan) {
 		ast_autoservice_start(autoservice_chan);
diff --git a/main/bridge.c b/main/bridge.c
index 88d9e548775577ad046f8f48b46518a32d338ef3..4f79852cb7a78113df9bea71aa09f455f41cf3d1 100644
--- a/main/bridge.c
+++ b/main/bridge.c
@@ -234,8 +234,21 @@ int __ast_bridge_technology_register(struct ast_bridge_technology *technology, s
 	/* Copy module pointer so reference counting can keep the module from unloading */
 	technology->mod = module;
 
-	/* Insert our new bridge technology into the list and print out a pretty message */
-	AST_RWLIST_INSERT_TAIL(&bridge_technologies, technology, entry);
+	/* Find the correct position to insert the technology. */
+	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&bridge_technologies, current, entry) {
+		/* Put the highest preference tech's first in the list. */
+		if (technology->preference >= current->preference) {
+			AST_RWLIST_INSERT_BEFORE_CURRENT(technology, entry);
+
+			break;
+		}
+	}
+	AST_RWLIST_TRAVERSE_SAFE_END;
+
+	if (!current) {
+		/* Insert our new bridge technology to the end of the list. */
+		AST_RWLIST_INSERT_TAIL(&bridge_technologies, technology, entry);
+	}
 
 	AST_RWLIST_UNLOCK(&bridge_technologies);
 
@@ -517,12 +530,17 @@ static struct ast_bridge_technology *find_best_technology(uint32_t capabilities,
 				current->name);
 			continue;
 		}
+		if (!ast_module_running_ref(current->mod)) {
+			ast_debug(1, "Bridge technology %s is not running, skipping.\n", current->name);
+			continue;
+		}
+		if (best) {
+			ast_module_unref(best->mod);
+		}
 		best = current;
 	}
 
 	if (best) {
-		/* Increment it's module reference count if present so it does not get unloaded while in use */
-		ast_module_ref(best->mod);
 		ast_debug(1, "Chose bridge technology %s\n", best->name);
 	}
 
diff --git a/main/cli.c b/main/cli.c
index 1299c2aa7aea4aff7ef242535cd8c90509b528b7..80c1843281bff3a6af886bdd2e68e3599082cce3 100644
--- a/main/cli.c
+++ b/main/cli.c
@@ -2679,9 +2679,12 @@ static char *__ast_cli_generator(const char *text, const char *word, int state,
 					.n = state - matchnum,
 					.argv = argv,
 					.argc = x};
-				ast_module_ref(e->module);
-				ret = e->handler(e, CLI_GENERATE, &a);
-				ast_module_unref(e->module);
+
+				/* If the command is in a module it must be running. */
+				if (!e->module || ast_module_running_ref(e->module)) {
+					ret = e->handler(e, CLI_GENERATE, &a);
+					ast_module_unref(e->module);
+				}
 			}
 			if (ret)
 				break;
@@ -2760,9 +2763,11 @@ int ast_cli_command_full(int uid, int gid, int fd, const char *s)
 	 */
 	args[0] = (char *)e;
 
-	ast_module_ref(e->module);
-	retval = e->handler(e, CLI_HANDLER, &a);
-	ast_module_unref(e->module);
+	/* If the command is in a module it must be running. */
+	if (!e->module || ast_module_running_ref(e->module)) {
+		retval = e->handler(e, CLI_HANDLER, &a);
+		ast_module_unref(e->module);
+	}
 
 	if (retval == CLI_SHOWUSAGE) {
 		ast_cli(fd, "%s", S_OR(e->usage, "Invalid usage, but no usage information available.\n"));
diff --git a/main/file.c b/main/file.c
index 41131f9eebc3dbc151157dbea8b4d3a593143c3b..8dded812382054f29344267bf4a2753d5ae79da7 100644
--- a/main/file.c
+++ b/main/file.c
@@ -425,11 +425,17 @@ static void filestream_destructor(void *arg)
 static struct ast_filestream *get_filestream(struct ast_format_def *fmt, FILE *bfile)
 {
 	struct ast_filestream *s;
-
 	int l = sizeof(*s) + fmt->buf_size + fmt->desc_size;	/* total allocation size */
-	if ( (s = ao2_alloc(l, filestream_destructor)) == NULL)
+
+	if (!ast_module_running_ref(fmt->module)) {
+		return NULL;
+	}
+
+	s = ao2_alloc(l, filestream_destructor);
+	if (!s) {
+		ast_module_unref(fmt->module);
 		return NULL;
-	ast_module_ref(fmt->module);
+	}
 	s->fmt = fmt;
 	s->f = bfile;
 
diff --git a/main/loader.c b/main/loader.c
index fe18048efc9eaa01cf48d527539f20c879629e33..88c1cda97aeb4ebec6856a5c089cef6e5c747921 100644
--- a/main/loader.c
+++ b/main/loader.c
@@ -1702,6 +1702,16 @@ struct ast_module *__ast_module_ref(struct ast_module *mod, const char *file, in
 	return mod;
 }
 
+struct ast_module *__ast_module_running_ref(struct ast_module *mod,
+	const char *file, int line, const char *func)
+{
+	if (!mod || !mod->flags.running) {
+		return NULL;
+	}
+
+	return __ast_module_ref(mod, file, line, func);
+}
+
 void __ast_module_shutdown_ref(struct ast_module *mod, const char *file, int line, const char *func)
 {
 	if (!mod || mod->flags.keepuntilshutdown) {
diff --git a/main/manager.c b/main/manager.c
index 576978c31c3a205b14f4d4e58ecfdad90ee553a3..3aa910501a5b827fe391d9a1533334dc3e916767 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -2923,34 +2923,41 @@ int ast_hook_send_action(struct manager_custom_hook *hook, const char *msg)
 	}
 
 	action = astman_get_header(&m, "Action");
-	if (strcasecmp(action, "login")) {
+
+	do {
+		if (!strcasecmp(action, "login")) {
+			break;
+		}
+
 		act_found = action_find(action);
-		if (act_found) {
-			/*
-			 * we have to simulate a session for this action request
-			 * to be able to pass it down for processing
-			 * This is necessary to meet the previous design of manager.c
-			 */
-			s.hook = hook;
+		if (!act_found) {
+			break;
+		}
 
-			ao2_lock(act_found);
-			if (act_found->registered && act_found->func) {
-				if (act_found->module) {
-					ast_module_ref(act_found->module);
-				}
-				ao2_unlock(act_found);
+		/*
+		 * we have to simulate a session for this action request
+		 * to be able to pass it down for processing
+		 * This is necessary to meet the previous design of manager.c
+		 */
+		s.hook = hook;
+
+		ret = -1;
+		ao2_lock(act_found);
+		if (act_found->registered && act_found->func) {
+			struct ast_module *mod_ref = ast_module_running_ref(act_found->module);
+
+			ao2_unlock(act_found);
+			/* If the action is in a module it must be running. */
+			if (!act_found->module || mod_ref) {
 				ret = act_found->func(&s, &m);
-				ao2_lock(act_found);
-				if (act_found->module) {
-					ast_module_unref(act_found->module);
-				}
-			} else {
-				ret = -1;
+				ast_module_unref(mod_ref);
 			}
+		} else {
 			ao2_unlock(act_found);
-			ao2_t_ref(act_found, -1, "done with found action object");
 		}
-	}
+		ao2_t_ref(act_found, -1, "done with found action object");
+	} while (0);
+
 	ast_free(dup_str);
 	return ret;
 }
@@ -6442,21 +6449,21 @@ static int process_message(struct mansession *s, const struct message *m)
 		if ((s->session->writeperm & act_found->authority)
 			|| act_found->authority == 0) {
 			/* We have the authority to execute the action. */
+			ret = -1;
 			ao2_lock(act_found);
 			if (act_found->registered && act_found->func) {
-				ast_debug(1, "Running action '%s'\n", act_found->action);
-				if (act_found->module) {
-					ast_module_ref(act_found->module);
-				}
+				struct ast_module *mod_ref = ast_module_running_ref(act_found->module);
+
 				ao2_unlock(act_found);
-				ret = act_found->func(s, m);
-				acted = 1;
-				ao2_lock(act_found);
-				if (act_found->module) {
-					ast_module_unref(act_found->module);
+				if (mod_ref || !act_found->module) {
+					ast_debug(1, "Running action '%s'\n", act_found->action);
+					ret = act_found->func(s, m);
+					acted = 1;
+					ast_module_unref(mod_ref);
 				}
+			} else {
+				ao2_unlock(act_found);
 			}
-			ao2_unlock(act_found);
 		}
 		if (!acted) {
 			/*
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index 76bdf87b09359dc753e74fe0c70768876a7e0d18..1c734778fd3c4da118451675af52228260ba1f37 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -428,6 +428,7 @@ struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name,
 	struct ast_sockaddr address = {{0,}};
 	struct ast_rtp_instance *instance = NULL;
 	struct ast_rtp_engine *engine = NULL;
+	struct ast_module *mod_ref;
 
 	AST_RWLIST_RDLOCK(&engines);
 
@@ -450,10 +451,15 @@ struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name,
 	}
 
 	/* Bump up the reference count before we return so the module can not be unloaded */
-	ast_module_ref(engine->mod);
+	mod_ref = ast_module_running_ref(engine->mod);
 
 	AST_RWLIST_UNLOCK(&engines);
 
+	if (!mod_ref) {
+		/* BUGBUG: improve handling of this situation. */
+		return NULL;
+	}
+
 	/* Allocate a new RTP instance */
 	if (!(instance = ao2_alloc(sizeof(*instance), instance_destructor))) {
 		ast_module_unref(engine->mod);
diff --git a/main/sorcery.c b/main/sorcery.c
index a55d5c72e36f3acf3286f6021a7ab7a09bd9dddb..c79675cd8c7521055d6b896354b3ccf8b7caf6ca 100644
--- a/main/sorcery.c
+++ b/main/sorcery.c
@@ -835,16 +835,19 @@ enum ast_sorcery_apply_result __ast_sorcery_insert_wizard_mapping(struct ast_sor
 	RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, ao2_alloc(sizeof(*object_wizard), sorcery_object_wizard_destructor), ao2_cleanup);
 	int created = 0;
 
-	if (!wizard) {
+	if (!object_wizard) {
+		return AST_SORCERY_APPLY_FAIL;
+	}
+
+	if (!wizard || wizard->callbacks.module != ast_module_running_ref(wizard->callbacks.module)) {
 		ast_log(LOG_ERROR, "Wizard '%s' could not be applied to object type '%s' as it was not found\n",
 			name, type);
 		return AST_SORCERY_APPLY_FAIL;
-	} else if (!object_wizard) {
-		return AST_SORCERY_APPLY_FAIL;
 	}
 
 	if (!object_type) {
 		if (!(object_type = sorcery_object_type_alloc(type, module))) {
+			ast_module_unref(wizard->callbacks.module);
 			return AST_SORCERY_APPLY_FAIL;
 		}
 		created = 1;
@@ -861,6 +864,7 @@ enum ast_sorcery_apply_result __ast_sorcery_insert_wizard_mapping(struct ast_sor
 			ast_debug(1, "Wizard %s already applied to object type %s\n",
 					wizard->callbacks.name, object_type->name);
 			AST_VECTOR_RW_UNLOCK(&object_type->wizards);
+			ast_module_unref(wizard->callbacks.module);
 			return AST_SORCERY_APPLY_DUPLICATE;
 		}
 	}
@@ -871,11 +875,10 @@ enum ast_sorcery_apply_result __ast_sorcery_insert_wizard_mapping(struct ast_sor
 		ast_log(LOG_WARNING, "Wizard '%s' failed to open mapping for object type '%s' with data: %s\n",
 			name, object_type->name, S_OR(data, ""));
 		AST_VECTOR_RW_UNLOCK(&object_type->wizards);
+		ast_module_unref(wizard->callbacks.module);
 		return AST_SORCERY_APPLY_FAIL;
 	}
 
-	ast_module_ref(wizard->callbacks.module);
-
 	object_wizard->wizard = ao2_bump(wizard);
 	object_wizard->caching = caching;
 
diff --git a/main/timing.c b/main/timing.c
index c6a9480c32ba906baac19ae6f073f9eeab40748c..18852c652a6654f47ebbfe18584c437ad1eade38 100644
--- a/main/timing.c
+++ b/main/timing.c
@@ -124,17 +124,22 @@ struct ast_timer *ast_timer_open(void)
 	void *data = NULL;
 	struct timing_holder *h;
 	struct ast_timer *t = NULL;
+	int idx = 1;
 
 	ast_heap_rdlock(timing_interfaces);
 
-	if ((h = ast_heap_peek(timing_interfaces, 1))) {
-		data = h->iface->timer_open();
-		ast_module_ref(h->mod);
+	while ((h = ast_heap_peek(timing_interfaces, idx))) {
+		if (ast_module_running_ref(h->mod)) {
+			data = h->iface->timer_open();
+			break;
+		}
+		idx++;
 	}
 
 	if (data) {
 		if (!(t = ast_calloc(1, sizeof(*t)))) {
 			h->iface->timer_close(data);
+			ast_module_unref(h->mod);
 		} else {
 			t->data = data;
 			t->holder = h;
diff --git a/main/translate.c b/main/translate.c
index 02717c5ed1ed6da989645146224bc9c937654efd..3d4905723c905efcc7582c7ae2b036dc0fc2df24 100644
--- a/main/translate.c
+++ b/main/translate.c
@@ -342,7 +342,10 @@ static struct ast_trans_pvt *newpvt(struct ast_translator *t, struct ast_format
 	 */
 	pvt->explicit_dst = ao2_bump(explicit_dst);
 
-	ast_module_ref(t->module);
+	if (!ast_module_running_ref(t->module)) {
+		ast_free(pvt);
+		return NULL;
+	}
 
 	/* call local init routine, if present */
 	if (t->newpvt && t->newpvt(pvt)) {
diff --git a/res/res_agi.c b/res/res_agi.c
index 85914c0189caf3f880e325ad40c214c43c87407d..393a503511a2139ad592848eccc322c5b6cc3e3f 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -4040,14 +4040,19 @@ static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, ch
 
 	parse_args(buf, &argc, argv);
 	c = find_command(argv, 0);
-	if (c && (!dead || (dead && c->dead))) {
-		/* if this command wasn't registered by res_agi, be sure to usecount
-		the module we are using */
-		if (c->mod != ast_module_info->self)
-			ast_module_ref(c->mod);
+	if (!c || !ast_module_running_ref(c->mod)) {
+		ami_res = "Invalid or unknown command";
+		resultcode = 510;
+
+		ast_agi_send(agi->fd, chan, "%d %s\n", resultcode, ami_res);
+
+		publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
+
+		return AGI_RESULT_SUCCESS;
+	}
+
+	if (!dead || (dead && c->dead)) {
 		res = c->handler(chan, agi, argc, argv);
-		if (c->mod != ast_module_info->self)
-			ast_module_unref(c->mod);
 		switch (res) {
 		case RESULT_SHOWUSAGE:
 			ami_res = "Usage";
@@ -4094,21 +4099,15 @@ static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, ch
 
 			break;
 		}
-	} else if (c) {
+	} else {
 		ami_res = "Command Not Permitted on a dead channel or intercept routine";
 		resultcode = 511;
 
 		ast_agi_send(agi->fd, chan, "%d %s\n", resultcode, ami_res);
 
-		publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
-	} else {
-		ami_res = "Invalid or unknown command";
-		resultcode = 510;
-
-		ast_agi_send(agi->fd, chan, "%d %s\n", resultcode, ami_res);
-
 		publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
 	}
+	ast_module_unref(c->mod);
 
 	return AGI_RESULT_SUCCESS;
 }
diff --git a/res/res_fax.c b/res/res_fax.c
index 0938452460b5515e3137129c96ccc32b1ef24948..4be5aee75a3c82e5cef46c78ae362ddee1b439a5 100644
--- a/res/res_fax.c
+++ b/res/res_fax.c
@@ -1161,8 +1161,10 @@ static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_detail
 		if ((faxmod->tech->caps & details->caps) != details->caps) {
 			continue;
 		}
+		if (!ast_module_running_ref(faxmod->tech->module)) {
+			continue;
+		}
 		ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
-		ast_module_ref(faxmod->tech->module);
 		s->tech = faxmod->tech;
 		break;
 	}
@@ -1279,8 +1281,10 @@ static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *d
 			if ((faxmod->tech->caps & details->caps) != details->caps) {
 				continue;
 			}
+			if (!ast_module_running_ref(faxmod->tech->module)) {
+				continue;
+			}
 			ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
-			ast_module_ref(faxmod->tech->module);
 			if (reserved) {
 				/* Balance module ref from reserved session */
 				ast_module_unref(reserved->tech->module);