From 8cc50b1ebc3fe6eacd2a03a8c8bc4800bdddfbe9 Mon Sep 17 00:00:00 2001 From: Corey Farrell Date: Wed, 11 Feb 2015 17:03:04 +0000 Subject: 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 --- main/loader.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) (limited to 'main/loader.c') 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(); } -- cgit v1.2.3