Core and Common Threads Stop and Start: Added timeout to the thread waiting loops. If we have waited more than five seconds we can be pretty sure that the thread is deadlocked. So then we can just as well continue and hope for the best.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2383 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2009-02-23 00:15:19 +00:00
parent 6bc6731f51
commit 472582022b
3 changed files with 18 additions and 5 deletions

View File

@ -91,7 +91,7 @@ void Thread::WaitForDeath()
{ {
if (m_hThread) if (m_hThread)
{ {
WaitForSingleObject(m_hThread, INFINITE); WaitForSingleObject(m_hThread, THREAD_WAIT_TIMEOUT);
CloseHandle(m_hThread); CloseHandle(m_hThread);
m_hThread = NULL; m_hThread = NULL;
} }
@ -140,7 +140,7 @@ void Event::Set()
void Event::Wait() void Event::Wait()
{ {
WaitForSingleObject(m_hEvent, INFINITE); WaitForSingleObject(m_hEvent, THREAD_WAIT_TIMEOUT);
} }
inline HRESULT MsgWaitForSingleObject(HANDLE handle, DWORD timeout) inline HRESULT MsgWaitForSingleObject(HANDLE handle, DWORD timeout)
@ -168,7 +168,7 @@ void Event::MsgWait()
// Wait for any message sent or posted to this queue // Wait for any message sent or posted to this queue
// or for one of the passed handles be set to signaled. // or for one of the passed handles be set to signaled.
result = MsgWaitForSingleObject(m_hEvent, INFINITE); result = MsgWaitForSingleObject(m_hEvent, THREAD_WAIT_TIMEOUT);
// The result tells us the type of event we have. // The result tells us the type of event we have.
if (result == (WAIT_OBJECT_0 + 1)) if (result == (WAIT_OBJECT_0 + 1))

View File

@ -81,6 +81,7 @@ private:
#ifdef _WIN32 #ifdef _WIN32
HANDLE m_hThread; HANDLE m_hThread;
DWORD m_threadId; DWORD m_threadId;
static const int THREAD_WAIT_TIMEOUT = 5000;
#else #else
pthread_t thread_id; pthread_t thread_id;
#endif #endif
@ -121,6 +122,12 @@ public:
private: private:
#ifdef _WIN32 #ifdef _WIN32
HANDLE m_hEvent; HANDLE m_hEvent;
/* If we have waited more than five seconds we can be pretty sure that the thread is deadlocked.
So then we can just as well continue and hope for the best. I could try several times that
this works after a five second timeout (with works meaning that the game stopped and I could
start another game without any noticable problems). But several times it failed to, and ended
with a crash. But it's better than an infinite deadlock. */
static const int THREAD_WAIT_TIMEOUT = 5000; // INFINITE or 5000 for example
#else #else
bool is_set_; bool is_set_;
pthread_cond_t event_; pthread_cond_t event_;

View File

@ -522,8 +522,14 @@ void CFrame::DoStop()
Core::Stop(); Core::Stop();
/* This is needed together with the option to not "delete g_EmuThread" in Core.cpp, because then /* This is needed together with the option to not "delete g_EmuThread" in Core.cpp, because then
we have to wait a moment before GetState() == CORE_UNINITIALIZED so that UpdateGUI() works */ we have to wait a moment before GetState() == CORE_UNINITIALIZED so that UpdateGUI() works.
#ifdef SETUP_AVOID_CHILD_WINDOW_RENDERING_HANG It's also needed when a WaitForSingleObject() has timed out so that the ShutDown() process
has continued without all threads having come to a rest. It's not compatible with the
SETUP_TIMER_WAITING option (because the Stop returns before it's finished).
Without this we just see the gray CPanel background because the ISO list will not be displayed.
*/
#ifndef SETUP_TIMER_WAITING
if (bRenderToMain) if (bRenderToMain)
while(Core::GetState() != Core::CORE_UNINITIALIZED) Sleep(10); while(Core::GetState() != Core::CORE_UNINITIALIZED) Sleep(10);
#endif #endif