diff options
author | Tanu Kaskinen <tanu.kaskinen@linux.intel.com> | 2014-12-05 15:51:35 +0200 |
---|---|---|
committer | Tanu Kaskinen <tanu.kaskinen@linux.intel.com> | 2014-12-05 16:07:59 +0200 |
commit | 2b6632e8518eb280bc6b86accb52233097200e9a (patch) | |
tree | 1bb4f29077c78b20a2f03acce4290fab2d990f0b | |
parent | 686baf80d92c47d8f1a41884b3e410ae9ec52e34 (diff) |
module: Fix unsafe iteration
This fixes an issue when requesting module unload for
module-bluetooth-discover. When unloading the module, it also unloads
module-bluez4-discover and/or module-bluez5-discover, and that
invalidated the state variable that was used for iterating through the
modules idxset.
The pa_module.unload_requested flag could now otherwise be removed,
but it's still being (ab)used in the bluetooth modules.
-rw-r--r-- | src/pulsecore/core.c | 6 | ||||
-rw-r--r-- | src/pulsecore/core.h | 1 | ||||
-rw-r--r-- | src/pulsecore/module.c | 9 |
3 files changed, 11 insertions, 5 deletions
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index e461963fc..c6fa8d730 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -117,7 +117,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, bool shared, size_t shm_size) { c->deferred_volume_extra_delay_usec = 0; c->module_defer_unload_event = NULL; - c->scache_auto_unload_event = NULL; + c->modules_pending_unload = pa_hashmap_new(NULL, NULL); c->subscription_defer_event = NULL; PA_LLIST_HEAD_INIT(pa_subscription, c->subscriptions); @@ -133,6 +133,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, bool shared, size_t shm_size) { pa_mempool_set_is_remote_writable(c->rw_mempool, true); c->exit_event = NULL; + c->scache_auto_unload_event = NULL; c->exit_idle_time = -1; c->scache_idle_time = 20; @@ -204,6 +205,9 @@ static void core_free(pa_object *o) { pa_assert(pa_hashmap_isempty(c->shared)); pa_hashmap_free(c->shared); + pa_assert(pa_hashmap_isempty(c->modules_pending_unload)); + pa_hashmap_free(c->modules_pending_unload); + pa_subscription_free_all(c); if (c->exit_event) diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 1f9df73e3..b0d121166 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -164,6 +164,7 @@ struct pa_core { int deferred_volume_extra_delay_usec; pa_defer_event *module_defer_unload_event; + pa_hashmap *modules_pending_unload; /* pa_module -> pa_module (hashmap-as-a-set) */ pa_defer_event *subscription_defer_event; PA_LLIST_HEAD(pa_subscription, subscriptions); diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c index bee8a20ef..49740349a 100644 --- a/src/pulsecore/module.c +++ b/src/pulsecore/module.c @@ -247,6 +247,8 @@ void pa_module_unload(pa_core *c, pa_module *m, bool force) { if (m->core->disallow_module_loading && !force) return; + pa_hashmap_remove(c->modules_pending_unload, m); + if (!(m = pa_idxset_remove_by_data(c->modules, m, NULL))) return; @@ -303,16 +305,14 @@ void pa_module_unload_all(pa_core *c) { } static void defer_cb(pa_mainloop_api*api, pa_defer_event *e, void *userdata) { - void *state = NULL; pa_core *c = PA_CORE(userdata); pa_module *m; pa_core_assert_ref(c); api->defer_enable(e, 0); - while ((m = pa_idxset_iterate(c->modules, &state, NULL))) - if (m->unload_requested) - pa_module_unload(c, m, true); + while ((m = pa_hashmap_first(c->modules_pending_unload))) + pa_module_unload(c, m, true); } void pa_module_unload_request(pa_module *m, bool force) { @@ -322,6 +322,7 @@ void pa_module_unload_request(pa_module *m, bool force) { return; m->unload_requested = true; + pa_hashmap_put(m->core->modules_pending_unload, m, m); if (!m->core->module_defer_unload_event) m->core->module_defer_unload_event = m->core->mainloop->defer_new(m->core->mainloop, defer_cb, m->core); |