From 472582022b7ebd39c6a52ff541c8beacd52739ca Mon Sep 17 00:00:00 2001 From: John Peterson Date: Mon, 23 Feb 2009 00:15:19 +0000 Subject: [PATCH] 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 --- Source/Core/Common/Src/Thread.cpp | 6 +++--- Source/Core/Common/Src/Thread.h | 7 +++++++ Source/Core/DolphinWX/Src/FrameTools.cpp | 10 ++++++++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Source/Core/Common/Src/Thread.cpp b/Source/Core/Common/Src/Thread.cpp index 7057a137ac..57196c837b 100644 --- a/Source/Core/Common/Src/Thread.cpp +++ b/Source/Core/Common/Src/Thread.cpp @@ -91,7 +91,7 @@ void Thread::WaitForDeath() { if (m_hThread) { - WaitForSingleObject(m_hThread, INFINITE); + WaitForSingleObject(m_hThread, THREAD_WAIT_TIMEOUT); CloseHandle(m_hThread); m_hThread = NULL; } @@ -140,7 +140,7 @@ void Event::Set() void Event::Wait() { - WaitForSingleObject(m_hEvent, INFINITE); + WaitForSingleObject(m_hEvent, THREAD_WAIT_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 // 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. if (result == (WAIT_OBJECT_0 + 1)) diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index b2d5274196..722cdf22f7 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -81,6 +81,7 @@ private: #ifdef _WIN32 HANDLE m_hThread; DWORD m_threadId; + static const int THREAD_WAIT_TIMEOUT = 5000; #else pthread_t thread_id; #endif @@ -121,6 +122,12 @@ public: private: #ifdef _WIN32 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 bool is_set_; pthread_cond_t event_; diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index daff3af44f..b468951873 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -522,8 +522,14 @@ void CFrame::DoStop() Core::Stop(); /* 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 */ - #ifdef SETUP_AVOID_CHILD_WINDOW_RENDERING_HANG + we have to wait a moment before GetState() == CORE_UNINITIALIZED so that UpdateGUI() works. + 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) while(Core::GetState() != Core::CORE_UNINITIALIZED) Sleep(10); #endif