X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4a268913a84bb934c62bc7685d736678528848d9..2d1715aa46b210e69ddf2dd1cd1c7d2f23c4298a:/src/msw/thread.cpp diff --git a/src/msw/thread.cpp b/src/msw/thread.cpp index cc035de03d..e179d3683f 100644 --- a/src/msw/thread.cpp +++ b/src/msw/thread.cpp @@ -484,7 +484,9 @@ THREAD_RETVAL THREAD_CALLCONV wxThreadInternal::WinThreadStart(void *param) // first of all, check whether we hadn't been cancelled already and don't // start the user code at all then - if ( thread->m_internal->GetState() == STATE_EXITED ) + bool isExited = (thread->m_internal->GetState() == STATE_EXITED); + + if ( isExited ) { rc = (THREAD_RETVAL)-1; } @@ -499,17 +501,23 @@ THREAD_RETVAL THREAD_CALLCONV wxThreadInternal::WinThreadStart(void *param) } rc = (THREAD_RETVAL)thread->Entry(); + } + + thread->OnExit(); + // save IsDetached because thread object can be deleted by joinable + // threads after state is changed to STATE_EXITED. + bool isDetached = thread->IsDetached(); + + if (!isExited) + { // enter m_critsect before changing the thread state wxCriticalSectionLocker lock(thread->m_critsect); - thread->m_internal->SetState(STATE_EXITED); } - thread->OnExit(); - // the thread may delete itself now if it wants, we don't need it any more - thread->m_internal->LetDie(); + if (isDetached) thread->m_internal->LetDie(); return rc; } @@ -769,15 +777,24 @@ wxThreadInternal::WaitForTerminate(wxCriticalSection& cs, // although the thread might be already in the EXITED state it might not // have terminated yet and so we are not sure that it has actually // terminated if the "if" above hadn't been taken - do + for ( ;; ) { if ( !::GetExitCodeThread(m_hThread, (LPDWORD)&rc) ) { wxLogLastError(wxT("GetExitCodeThread")); rc = (wxThread::ExitCode)-1; + + break; } - } while ( (DWORD)rc == STILL_ACTIVE ); + + if ( (DWORD)rc != STILL_ACTIVE ) + break; + + // give the other thread some time to terminate, otherwise we may be + // starving it + ::Sleep(1); + } if ( pRc ) *pRc = rc;