Fix possibly fatal race condition when calling OnDelete()

This function could be called on an already deleted object, which could
result in a crash, and always resulted in a TSAN error.

Fix this by calling it before releasing the internal lock, which
prevents this from happening, but will result in a deadlock if this
function is overridden to do something requiring any lock held by the
thread.

This is not ideal, but still seems to be like a lesser evil.
This commit is contained in:
Vadim Zeitlin 2023-03-12 18:27:24 +01:00
parent 345b8ff505
commit 59312f5ba0
2 changed files with 12 additions and 4 deletions

View file

@ -486,8 +486,10 @@ public:
will be executed in the context of the thread that called Delete() and
<b>not</b> in this thread's context.
TestDestroy() will be true for the thread before OnDelete() gets
executed.
Note that TestDestroy() will block until OnDelete() returns, so this
function should return as quickly as possible and definitely shouldn't
perform any GUI actions nor try acquiring any locks, as this could
easily result in a deadlock.
@since 2.9.2

View file

@ -1575,10 +1575,16 @@ wxThreadError wxThread::Delete(ExitCode *rc, wxThreadWait WXUNUSED(waitMode))
// ask the thread to stop
m_internal->SetCancelFlag();
m_critsect.Leave();
// Normally we should never call out while holding the lock (on m_critsect
// in this case), but we can't do it later because as soon as we unlock it,
// this object may be destroyed as the thread executing its Entry() may
// call TestDestroy() and decide to exit at any moment, so we have to do it
// now and hope that OnDelete() doesn't do anything stupid (or, preferably,
// anything at all).
OnDelete();
m_critsect.Leave();
switch ( state )
{
case STATE_NEW: