From 498bd544a4b4bbedeb178dd0200821d95be52592 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Mon, 29 Oct 2018 00:47:29 -0400 Subject: [PATCH] freebsd11_network: Fix race condition leading to lock of deleted mutex. * Initialize "status" to B_NO_INIT, which will skip the main 'if' the first go-around and go straight to the acquire_sem_etc(), as we will have be invoked from the callout initializer, and so there will of course be no callouts. * Actually check the return code of mutex_lock, and do another loop iteration (which skips this main 'if' as status will not be one of those things.) * Correct failure deinitialization order in init_callout(). * Destroy the mutex after the worker thread exits (this is the real fix.) Fixes #14660, and other "hang on cursor" / "hang on black screen" / or possibly even a "hang on rocket" introduced in yesterday's builds. --- src/libs/compat/freebsd11_network/callout.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/libs/compat/freebsd11_network/callout.cpp b/src/libs/compat/freebsd11_network/callout.cpp index 7f2315ca3e..681f50fcfb 100644 --- a/src/libs/compat/freebsd11_network/callout.cpp +++ b/src/libs/compat/freebsd11_network/callout.cpp @@ -37,14 +37,15 @@ static bigtime_t sTimeout; static status_t callout_thread(void* /*data*/) { - status_t status = B_OK; + status_t status = B_NO_INIT; do { bigtime_t timeout = B_INFINITE_TIMEOUT; if (status == B_TIMED_OUT || status == B_OK) { // scan timers for new timeout and/or execute a timer - mutex_lock(&sLock); + if ((status = mutex_lock(&sLock)) != B_OK) + continue; struct callout* c = NULL; while (true) { @@ -71,7 +72,8 @@ callout_thread(void* /*data*/) && (c->c_flags & CALLOUT_RETURNUNLOCKED) == 0) mtx_unlock(mutex); - mutex_lock(&sLock); + if ((status = mutex_lock(&sLock)) != B_OK) + continue; sCurrentCallout = NULL; c = NULL; @@ -127,10 +129,10 @@ init_callout(void) return resume_thread(sThread); -err1: - mutex_destroy(&sLock); err2: delete_sem(sWaitSem); +err1: + mutex_destroy(&sLock); return status; } @@ -139,12 +141,11 @@ void uninit_callout(void) { delete_sem(sWaitSem); + + wait_for_thread(sThread, NULL); + mutex_lock(&sLock); - mutex_destroy(&sLock); - - status_t status; - wait_for_thread(sThread, &status); }