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.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user