From 9a6f8d31dc36202f32c474c15d38cacda702e706 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 26 Jun 2025 14:23:36 +0200 Subject: [PATCH] loop: unlock the lock when blocking on invoke When we are the owners of the loop lock and we are not in the loop thread itself, release all locks so that the loop can start processing our invoke items and we get a chance to make progress. After that re-acquire the locks. This can happen when you change some of the core loop_locked() calls to blocking _invoke functions that are called with the loop locked. We have all core blocking invoke functions removed now so this is not actually going to be used but just in case an application tries to blocking invoke while locking the loop, this will now at least do something else than deadlock. --- spa/plugins/support/loop.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/spa/plugins/support/loop.c b/spa/plugins/support/loop.c index 2f4559651..f65454b67 100644 --- a/spa/plugins/support/loop.c +++ b/spa/plugins/support/loop.c @@ -477,11 +477,27 @@ again: if (block && queue->ack_fd != -1) { uint64_t count = 1; + int i, recurse = 0; + + if (pthread_mutex_trylock(&impl->lock) == 0) { + /* we are holding the lock, unlock recurse times */ + recurse = impl->recurse; + while (impl->recurse > 0) { + impl->recurse--; + pthread_mutex_unlock(&impl->lock); + } + pthread_mutex_unlock(&impl->lock); + } if ((res = spa_system_eventfd_read(impl->system, queue->ack_fd, &count)) < 0) spa_log_warn(impl->log, "%p: failed to read event fd:%d: %s", queue, queue->ack_fd, spa_strerror(res)); + for (i = 0; i < recurse; i++) { + pthread_mutex_lock(&impl->lock); + impl->recurse++; + } + res = item->res; } else {