summaryrefslogtreecommitdiff
path: root/src/pulsecore
diff options
context:
space:
mode:
authorTanu Kaskinen <tanuk@iki.fi>2016-09-21 12:55:08 +0300
committerTanu Kaskinen <tanuk@iki.fi>2016-12-12 17:18:49 +0200
commit509cfd9138c59802ece75e8ebd43b0b07c28c6d0 (patch)
tree6eb9b9ece70356b501f541c50d7b58dfcf858eeb /src/pulsecore
parentc81f3da53b908a05e6325b6bc0dfb4cd5b08f8ec (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/pulsecore')
-rw-r--r--src/pulsecore/module.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c
index 7cba3a76..ac158159 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);