summaryrefslogtreecommitdiff
path: root/main/loader.c
diff options
context:
space:
mode:
authorCorey Farrell <git@cfware.com>2015-02-11 17:03:04 +0000
committerCorey Farrell <git@cfware.com>2015-02-11 17:03:04 +0000
commit8cc50b1ebc3fe6eacd2a03a8c8bc4800bdddfbe9 (patch)
treeda998029b1bb125ecdec651fe89ce3f0f9b8a5d6 /main/loader.c
parent137c4b0778928040dff81f15b770211ee1ead320 (diff)
Enable REF_DEBUG for ast_module_ref / ast_module_unref.
Add ast_module_shutdown_ref for use by modules that can only be unloaded during graceful shutdown. When REF_DEBUG is enabled: * Add an empty ao2 object to struct ast_module. * Allocate ao2 object when the module is loaded. * Perform an ao2_ref in each place where mod->usecount is manipulated. * ao2_cleanup on module unload. ASTERISK-24479 #close Reported by: Corey Farrell Review: https://reviewboard.asterisk.org/r/4141/ ........ Merged revisions 431662 from http://svn.asterisk.org/svn/asterisk/branches/11 ........ Merged revisions 431663 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@431672 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/loader.c')
-rw-r--r--main/loader.c56
1 files changed, 54 insertions, 2 deletions
diff --git a/main/loader.c b/main/loader.c
index f80e72634..5d644ed6b 100644
--- a/main/loader.c
+++ b/main/loader.c
@@ -117,12 +117,17 @@ static unsigned int embedding = 1; /* we always start out by registering embedde
struct ast_module {
const struct ast_module_info *info;
+#ifdef REF_DEBUG
+ /* Used to get module references into REF_DEBUG logs */
+ void *ref_debug;
+#endif
void *lib; /* the shared lib, or NULL if embedded */
int usecount; /* the number of 'users' currently in this module */
struct module_user_list users; /* the list of users in the module */
struct {
unsigned int running:1;
unsigned int declined:1;
+ unsigned int keepuntilshutdown:1;
} flags;
AST_LIST_ENTRY(ast_module) list_entry;
AST_DLLIST_ENTRY(ast_module) entry;
@@ -189,6 +194,9 @@ void ast_module_register(const struct ast_module_info *info)
ast_debug(5, "Registering module %s\n", info->name);
mod->info = info;
+#ifdef REF_DEBUG
+ mod->ref_debug = ao2_t_alloc(0, NULL, info->name);
+#endif
AST_LIST_HEAD_INIT(&mod->users);
/* during startup, before the loader has been initialized,
@@ -235,6 +243,9 @@ void ast_module_unregister(const struct ast_module_info *info)
if (mod) {
ast_debug(5, "Unregistering module %s\n", info->name);
AST_LIST_HEAD_DESTROY(&mod->users);
+#ifdef REF_DEBUG
+ ao2_cleanup(mod->ref_debug);
+#endif
ast_free(mod);
}
}
@@ -254,6 +265,10 @@ struct ast_module_user *__ast_module_user_add(struct ast_module *mod, struct ast
AST_LIST_INSERT_HEAD(&mod->users, u, entry);
AST_LIST_UNLOCK(&mod->users);
+#ifdef REF_DEBUG
+ ao2_ref(mod->ref_debug, +1);
+#endif
+
ast_atomic_fetchadd_int(&mod->usecount, +1);
ast_update_use_count();
@@ -278,6 +293,10 @@ void __ast_module_user_remove(struct ast_module *mod, struct ast_module_user *u)
return;
}
+#ifdef REF_DEBUG
+ ao2_ref(mod->ref_debug, -1);
+#endif
+
ast_atomic_fetchadd_int(&mod->usecount, -1);
ast_free(u);
@@ -293,6 +312,11 @@ void __ast_module_user_hangup_all(struct ast_module *mod)
if (u->chan) {
ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
}
+
+#ifdef REF_DEBUG
+ ao2_ref(mod->ref_debug, -1);
+#endif
+
ast_atomic_fetchadd_int(&mod->usecount, -1);
ast_free(u);
}
@@ -610,10 +634,22 @@ void ast_module_shutdown(void)
mod->info->unload();
}
AST_LIST_HEAD_DESTROY(&mod->users);
+#ifdef REF_DEBUG
+ ao2_cleanup(mod->ref_debug);
+#endif
ast_free(mod);
somethingchanged = 1;
}
AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END;
+ if (!somethingchanged) {
+ AST_DLLIST_TRAVERSE(&module_list, mod, entry) {
+ if (mod->flags.keepuntilshutdown) {
+ ast_module_unref(mod);
+ mod->flags.keepuntilshutdown = 0;
+ somethingchanged = 1;
+ }
+ }
+ }
} while (somethingchanged && !final);
AST_DLLIST_UNLOCK(&module_list);
@@ -1430,24 +1466,40 @@ int ast_loader_unregister(int (*v)(void))
return cur ? 0 : -1;
}
-struct ast_module *ast_module_ref(struct ast_module *mod)
+struct ast_module *__ast_module_ref(struct ast_module *mod, const char *file, int line, const char *func)
{
if (!mod) {
return NULL;
}
+#ifdef REF_DEBUG
+ __ao2_ref_debug(mod->ref_debug, +1, "", file, line, func);
+#endif
+
ast_atomic_fetchadd_int(&mod->usecount, +1);
ast_update_use_count();
return mod;
}
-void ast_module_unref(struct ast_module *mod)
+void __ast_module_shutdown_ref(struct ast_module *mod, const char *file, int line, const char *func)
+{
+ if (!mod->flags.keepuntilshutdown) {
+ __ast_module_ref(mod, file, line, func);
+ mod->flags.keepuntilshutdown = 1;
+ }
+}
+
+void __ast_module_unref(struct ast_module *mod, const char *file, int line, const char *func)
{
if (!mod) {
return;
}
+#ifdef REF_DEBUG
+ __ao2_ref_debug(mod->ref_debug, -1, "", file, line, func);
+#endif
+
ast_atomic_fetchadd_int(&mod->usecount, -1);
ast_update_use_count();
}