Skip to content

Commit c209064

Browse files
InterLinked1gtjoseph
authored andcommitted
loader: Allow declined modules to be unloaded.
Currently, if a module declines to load, dlopen is called to register the module but dlclose never gets called. Furthermore, loader.c currently doesn't allow dlclose to ever get called on the module, since it declined to load and the unload function bails early in this case. This can be problematic if a module is updated, since the new module cannot be loaded into memory since we haven't closed all references to it. To fix this, we now allow modules to be unloaded, even if they never "loaded" in Asterisk itself, so that dlclose is called and the module can be properly cleaned up, allowing the updated module to be loaded from scratch next time. ASTERISK-30345 #close Change-Id: Ifc743aadfa85ebe3284e02a63e124dafa64988d5
1 parent f772643 commit c209064

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

main/loader.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,8 +1241,17 @@ int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode f
12411241
}
12421242

12431243
if (!mod->flags.running || mod->flags.declined) {
1244-
ast_log(LOG_WARNING, "Unload failed, '%s' is not loaded.\n", resource_name);
1245-
error = 1;
1244+
/* If the user asks to unload a module that didn't load, obey.
1245+
* Otherwise, we never dlclose() modules that fail to load,
1246+
* which means if the module (shared object) is updated,
1247+
* we can't load the updated module since we never dlclose()'d it.
1248+
* Accordingly, obey the unload request so we can load the module
1249+
* from scratch next time.
1250+
*/
1251+
ast_log(LOG_NOTICE, "Unloading module '%s' that previously declined to load\n", resource_name);
1252+
error = 0;
1253+
res = 0;
1254+
goto exit; /* Skip all the intervening !error checks, only the last one is relevant. */
12461255
}
12471256

12481257
if (!error && (mod->usecount > 0)) {
@@ -1284,6 +1293,7 @@ int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode f
12841293
if (!error)
12851294
mod->flags.running = mod->flags.declined = 0;
12861295

1296+
exit:
12871297
AST_DLLIST_UNLOCK(&module_list);
12881298

12891299
if (!error) {
@@ -1823,7 +1833,18 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi
18231833

18241834
int ast_load_resource(const char *resource_name)
18251835
{
1836+
struct ast_module *mod;
18261837
int res;
1838+
1839+
/* If we're trying to load a module that previously declined to load,
1840+
* transparently unload it first so we dlclose, then dlopen it afresh.
1841+
* Otherwise, we won't actually load a (potentially) updated module. */
1842+
mod = find_resource(resource_name, 0);
1843+
if (mod && mod->flags.declined) {
1844+
ast_debug(1, "Module %s previously declined to load, unloading it first before loading again\n", resource_name);
1845+
ast_unload_resource(resource_name, 0);
1846+
}
1847+
18271848
AST_DLLIST_LOCK(&module_list);
18281849
res = load_resource(resource_name, 0, NULL, 0, 0);
18291850
if (!res) {

0 commit comments

Comments
 (0)