loop: add spa_goto_if_fail and use in loop_enter

When we lock and enter the loop but it is not the right thread, unlock
it again after logging an error. Otherwise we might deadlock.
This commit is contained in:
Wim Taymans 2026-05-05 17:50:39 +02:00
parent 593b5cf148
commit f57a2e9680
2 changed files with 17 additions and 3 deletions

View file

@ -386,6 +386,16 @@ struct spa_error_location {
} \ } \
} while(false) } while(false)
#define spa_goto_if_fail(expr, label) \
do { \
if (SPA_UNLIKELY(!(expr))) { \
fprintf(stderr, "'%s' failed at %s:%u %s()\n", \
#expr , __FILE__, __LINE__, __func__); \
goto label; \
} \
} while(false)
/* spa_assert_se() is an assert which guarantees side effects of x, /* spa_assert_se() is an assert which guarantees side effects of x,
* i.e. is never optimized away, regardless of NDEBUG or FASTPATH. */ * i.e. is never optimized away, regardless of NDEBUG or FASTPATH. */
#ifndef __COVERITY__ #ifndef __COVERITY__

View file

@ -605,15 +605,19 @@ static void loop_enter(void *object)
spa_assert_se(pthread_mutex_lock(&impl->lock) == 0); spa_assert_se(pthread_mutex_lock(&impl->lock) == 0);
if (impl->enter_count == 0) { if (impl->enter_count == 0) {
spa_return_if_fail(impl->thread == 0); spa_goto_if_fail(impl->thread == 0, unlock_error);
impl->thread = thread_id; impl->thread = thread_id;
impl->enter_count = 1; impl->enter_count = 1;
} else { } else {
spa_return_if_fail(impl->enter_count > 0); spa_goto_if_fail(impl->enter_count > 0, unlock_error);
spa_return_if_fail(pthread_equal(impl->thread, thread_id)); spa_goto_if_fail(pthread_equal(impl->thread, thread_id), unlock_error);
impl->enter_count++; impl->enter_count++;
} }
spa_log_trace_fp(impl->log, "%p: enter %p", impl, (void *) impl->thread); spa_log_trace_fp(impl->log, "%p: enter %p", impl, (void *) impl->thread);
return;
unlock_error:
pthread_mutex_unlock(&impl->lock);
} }
static void loop_leave(void *object) static void loop_leave(void *object)