mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
loop: make safe version of befor and after signal
Use a safer version of the before and after hooks. First call
all before hooks and save them in reverse order in a save list.
Then call the after event for the ones remaining in the save list
and move them back to the hook list.
This makes it possible to remove the hooks from one the callbacks or
even from other threads with the right locks. Found as a solution to
the following problem as observed in vlc:
main thread thread_loop
pw_thread_loop_lock() before hook: lock suspend thread
pw_context_destroy()
- removes before hook to flush clients
pw_thread_loop_unlock()
before hook: lock acquired, resume
before hook: flush client hook executed
*crash*
pw_thread_loop_stop()
pw_thread_loop_destroy()
Any of the safer cursor methods (like spa_hook_list_call()) would also
work but are more expensive and don't reverse the before/after
order.
This commit is contained in:
parent
b5517cc2fe
commit
05ae8a24de
1 changed files with 13 additions and 2 deletions
|
|
@ -278,13 +278,24 @@ static int loop_iterate(void *object, int timeout)
|
|||
struct impl *impl = object;
|
||||
struct spa_loop *loop = &impl->loop;
|
||||
struct spa_poll_event ep[32];
|
||||
struct spa_list save;
|
||||
struct spa_hook *hook;
|
||||
int i, nfds;
|
||||
|
||||
spa_loop_control_hook_before(&impl->hooks_list);
|
||||
spa_list_init(&save);
|
||||
spa_list_consume(hook, &impl->hooks_list.list, link) {
|
||||
spa_list_remove(&hook->link);
|
||||
spa_list_prepend(&save, &hook->link);
|
||||
spa_callbacks_call(&hook->cb, struct spa_loop_control_hooks, before, 0);
|
||||
}
|
||||
|
||||
nfds = spa_system_pollfd_wait(impl->system, impl->poll_fd, ep, SPA_N_ELEMENTS(ep), timeout);
|
||||
|
||||
spa_loop_control_hook_after(&impl->hooks_list);
|
||||
spa_list_consume(hook, &save, link) {
|
||||
spa_list_remove(&hook->link);
|
||||
spa_list_append(&impl->hooks_list.list, &hook->link);
|
||||
spa_callbacks_call(&hook->cb, struct spa_loop_control_hooks, after, 0);
|
||||
}
|
||||
|
||||
if (SPA_UNLIKELY(nfds < 0))
|
||||
return nfds;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue