diff options
author | Tanu Kaskinen <tanuk@iki.fi> | 2016-09-21 12:55:08 +0300 |
---|---|---|
committer | Tanu Kaskinen <tanuk@iki.fi> | 2016-12-12 17:18:49 +0200 |
commit | 509cfd9138c59802ece75e8ebd43b0b07c28c6d0 (patch) | |
tree | 6eb9b9ece70356b501f541c50d7b58dfcf858eeb /src | |
parent | c81f3da53b908a05e6325b6bc0dfb4cd5b08f8ec (diff) |
module: postpone lt_dlclose() until a safe time
When unloading a module, lt_dlclose() may remove the module from memory.
If a module unloads itself, it's not safe to call lt_dlclose()
synchronously from pa_module_unload(), because the execution may return
to the module code that was removed from memory. To avoid this
situation, let's postpone lt_dlclose() until it's safe to call it.
BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=96831
Diffstat (limited to 'src')
-rw-r--r-- | src/pulsecore/module.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c index 7cba3a761..ac1581591 100644 --- a/src/pulsecore/module.c +++ b/src/pulsecore/module.c @@ -228,6 +228,12 @@ fail: return NULL; } +static void postponed_dlclose(pa_mainloop_api *api, void *userdata) { + lt_dlhandle dl = userdata; + + lt_dlclose(dl); +} + static void pa_module_free(pa_module *m) { pa_assert(m); pa_assert(m->core); @@ -246,7 +252,15 @@ static void pa_module_free(pa_module *m) { if (m->proplist) pa_proplist_free(m->proplist); - lt_dlclose(m->dl); + /* If a module unloads itself with pa_module_unload(), we can't call + * lt_dlclose() here, because otherwise pa_module_unload() may return to a + * code location that has been removed from memory. Therefore, let's + * postpone the lt_dlclose() call a bit. + * + * Apparently lt_dlclose() doesn't always remove the module from memory, + * but it can happen, as can be seen here: + * https://bugs.freedesktop.org/show_bug.cgi?id=96831 */ + pa_mainloop_api_once(m->core->mainloop, postponed_dlclose, m->dl); pa_hashmap_remove(m->core->modules_pending_unload, m); |