Ensure that wxThread::Pause() suspends the thread immediately

Surprisingly, ::SuspendThread() doesn't actually do it, but only
schedules the thread for suspension in some undetermined near future.
This could result in problems as Pause() could exit, releasing the CS
protecting wxThread internal data in the main thread, and allowing the
worker thread to enter it (e.g. in its TestDestroy()) before being
actually suspended, meaning that the thread got suspended inside a CS,
which resulted in later deadlocks.

Fix this by calling ::GetThreadContext() which is supposed to ensure
that the scheduler does really suspend the thread before it returns (as
it's impossible to get the context of a thread while it's running).

Closes #18137.
This commit is contained in:
Vadim Zeitlin
2018-07-06 19:01:38 +02:00
parent 832f837f75
commit 5d06593ae1

View File

@@ -875,6 +875,20 @@ bool wxThreadInternal::Suspend()
return false;
}
// Calling GetThreadContext() forces the thread to actually be suspended:
// just calling SuspendThread() is not enough, it just asks the scheduler
// to suspend the thread at the next opportunity and by then we may already
// exit wxThread::Pause() and leave m_critsect, meaning that the thread
// could enter it and end up suspended inside a CS, which will inevitably
// result in a deadlock later.
CONTEXT ctx;
// We don't really need the context, but we still must initialize it.
ctx.ContextFlags = CONTEXT_FULL;
if ( !::GetThreadContext(m_hThread, &ctx) )
{
wxLogLastError(wxS("GetThreadContext"));
}
m_state = STATE_PAUSED;
return true;