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.
This commit is contained in:
Wim Taymans 2025-06-26 14:23:36 +02:00
parent 17c755714d
commit 9a6f8d31dc

View file

@ -477,11 +477,27 @@ again:
if (block && queue->ack_fd != -1) { if (block && queue->ack_fd != -1) {
uint64_t count = 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) 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", spa_log_warn(impl->log, "%p: failed to read event fd:%d: %s",
queue, queue->ack_fd, spa_strerror(res)); queue, queue->ack_fd, spa_strerror(res));
for (i = 0; i < recurse; i++) {
pthread_mutex_lock(&impl->lock);
impl->recurse++;
}
res = item->res; res = item->res;
} }
else { else {