mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-02 09:01:46 -05:00
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.
This commit is contained in:
parent
686baf80d9
commit
2b6632e851
3 changed files with 11 additions and 5 deletions
|
|
@ -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->deferred_volume_extra_delay_usec = 0;
|
||||||
|
|
||||||
c->module_defer_unload_event = NULL;
|
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;
|
c->subscription_defer_event = NULL;
|
||||||
PA_LLIST_HEAD_INIT(pa_subscription, c->subscriptions);
|
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);
|
pa_mempool_set_is_remote_writable(c->rw_mempool, true);
|
||||||
|
|
||||||
c->exit_event = NULL;
|
c->exit_event = NULL;
|
||||||
|
c->scache_auto_unload_event = NULL;
|
||||||
|
|
||||||
c->exit_idle_time = -1;
|
c->exit_idle_time = -1;
|
||||||
c->scache_idle_time = 20;
|
c->scache_idle_time = 20;
|
||||||
|
|
@ -204,6 +205,9 @@ static void core_free(pa_object *o) {
|
||||||
pa_assert(pa_hashmap_isempty(c->shared));
|
pa_assert(pa_hashmap_isempty(c->shared));
|
||||||
pa_hashmap_free(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);
|
pa_subscription_free_all(c);
|
||||||
|
|
||||||
if (c->exit_event)
|
if (c->exit_event)
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,7 @@ struct pa_core {
|
||||||
int deferred_volume_extra_delay_usec;
|
int deferred_volume_extra_delay_usec;
|
||||||
|
|
||||||
pa_defer_event *module_defer_unload_event;
|
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_defer_event *subscription_defer_event;
|
||||||
PA_LLIST_HEAD(pa_subscription, subscriptions);
|
PA_LLIST_HEAD(pa_subscription, subscriptions);
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,8 @@ void pa_module_unload(pa_core *c, pa_module *m, bool force) {
|
||||||
if (m->core->disallow_module_loading && !force)
|
if (m->core->disallow_module_loading && !force)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
pa_hashmap_remove(c->modules_pending_unload, m);
|
||||||
|
|
||||||
if (!(m = pa_idxset_remove_by_data(c->modules, m, NULL)))
|
if (!(m = pa_idxset_remove_by_data(c->modules, m, NULL)))
|
||||||
return;
|
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) {
|
static void defer_cb(pa_mainloop_api*api, pa_defer_event *e, void *userdata) {
|
||||||
void *state = NULL;
|
|
||||||
pa_core *c = PA_CORE(userdata);
|
pa_core *c = PA_CORE(userdata);
|
||||||
pa_module *m;
|
pa_module *m;
|
||||||
|
|
||||||
pa_core_assert_ref(c);
|
pa_core_assert_ref(c);
|
||||||
api->defer_enable(e, 0);
|
api->defer_enable(e, 0);
|
||||||
|
|
||||||
while ((m = pa_idxset_iterate(c->modules, &state, NULL)))
|
while ((m = pa_hashmap_first(c->modules_pending_unload)))
|
||||||
if (m->unload_requested)
|
pa_module_unload(c, m, true);
|
||||||
pa_module_unload(c, m, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pa_module_unload_request(pa_module *m, bool force) {
|
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;
|
return;
|
||||||
|
|
||||||
m->unload_requested = true;
|
m->unload_requested = true;
|
||||||
|
pa_hashmap_put(m->core->modules_pending_unload, m, m);
|
||||||
|
|
||||||
if (!m->core->module_defer_unload_event)
|
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);
|
m->core->module_defer_unload_event = m->core->mainloop->defer_new(m->core->mainloop, defer_cb, m->core);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue