diff --git a/spa/include/spa/utils/defs.h b/spa/include/spa/utils/defs.h index 440f7f7fd..d5b7928da 100644 --- a/spa/include/spa/utils/defs.h +++ b/spa/include/spa/utils/defs.h @@ -386,6 +386,16 @@ struct spa_error_location { } \ } 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, * i.e. is never optimized away, regardless of NDEBUG or FASTPATH. */ #ifndef __COVERITY__ diff --git a/spa/plugins/support/loop.c b/spa/plugins/support/loop.c index 5e35f6dcd..11c3fa222 100644 --- a/spa/plugins/support/loop.c +++ b/spa/plugins/support/loop.c @@ -605,15 +605,19 @@ static void loop_enter(void *object) spa_assert_se(pthread_mutex_lock(&impl->lock) == 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->enter_count = 1; } else { - spa_return_if_fail(impl->enter_count > 0); - spa_return_if_fail(pthread_equal(impl->thread, thread_id)); + spa_goto_if_fail(impl->enter_count > 0, unlock_error); + spa_goto_if_fail(pthread_equal(impl->thread, thread_id), unlock_error); impl->enter_count++; } 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)