diff --git a/renderdoc/core/core.cpp b/renderdoc/core/core.cpp index 5447ce7f6..1f116fe2f 100644 --- a/renderdoc/core/core.cpp +++ b/renderdoc/core/core.cpp @@ -259,7 +259,7 @@ RenderDoc::~RenderDoc() } m_RemoteServerThreadShutdown = true; - Threading::JoinThread(m_RemoteThread); + // don't join, just close the thread, as we can't wait while in the middle of module unloading Threading::CloseThread(m_RemoteThread); m_RemoteThread = 0; diff --git a/renderdoc/core/remote_access.cpp b/renderdoc/core/remote_access.cpp index 7d685b145..86a3fa5f1 100644 --- a/renderdoc/core/remote_access.cpp +++ b/renderdoc/core/remote_access.cpp @@ -44,6 +44,8 @@ enum PacketType void RenderDoc::RemoteAccessClientThread(void *s) { + Threading::KeepModuleAlive(); + Network::Socket *client = (Network::Socket *)s; Serialiser ser(L"", Serialiser::WRITING, false); @@ -66,7 +68,8 @@ void RenderDoc::RemoteAccessClientThread(void *s) SCOPED_LOCK(RenderDoc::Inst().m_SingleClientLock); RenderDoc::Inst().m_SingleClientName = L""; } - + + Threading::ReleaseModuleExitThread(); return; } @@ -204,10 +207,14 @@ void RenderDoc::RemoteAccessClientThread(void *s) SCOPED_LOCK(RenderDoc::Inst().m_SingleClientLock); RenderDoc::Inst().m_SingleClientName = L""; } + + Threading::ReleaseModuleExitThread(); } void RenderDoc::RemoteAccessServerThread(void *s) { + Threading::KeepModuleAlive(); + Network::Socket *sock = (Network::Socket *)s; RenderDoc::Inst().m_SingleClientName = L""; @@ -227,6 +234,7 @@ void RenderDoc::RemoteAccessServerThread(void *s) RDCERR("Error in accept - shutting down server"); SAFE_DELETE(sock); + Threading::ReleaseModuleExitThread(); return; } @@ -322,9 +330,11 @@ void RenderDoc::RemoteAccessServerThread(void *s) } RenderDoc::Inst().m_RemoteClientThreadShutdown = true; - Threading::JoinThread(clientThread); + // don't join, just close the thread, as we can't wait while in the middle of module unloading Threading::CloseThread(clientThread); clientThread = 0; + + Threading::ReleaseModuleExitThread(); } struct RemoteAccess diff --git a/renderdoc/os/linux/linux_threading.cpp b/renderdoc/os/linux/linux_threading.cpp index 79332cf55..d2e5bbc19 100644 --- a/renderdoc/os/linux/linux_threading.cpp +++ b/renderdoc/os/linux/linux_threading.cpp @@ -152,7 +152,15 @@ namespace Threading void CloseThread(ThreadHandle handle) { } + + void KeepModuleAlive() + { + } + void ReleaseModuleExitThread() + { + } + void Sleep(uint32_t milliseconds) { usleep(milliseconds*1000); diff --git a/renderdoc/os/os_specific.h b/renderdoc/os/os_specific.h index 2ada76bd7..fee2a020f 100644 --- a/renderdoc/os/os_specific.h +++ b/renderdoc/os/os_specific.h @@ -89,6 +89,11 @@ namespace Threading void JoinThread(ThreadHandle handle); void CloseThread(ThreadHandle handle); void Sleep(uint32_t milliseconds); + + // kind of windows specific, to handle this case: + // http://blogs.msdn.com/b/oldnewthing/archive/2013/11/05/10463645.aspx + void KeepModuleAlive(); + void ReleaseModuleExitThread(); }; namespace Network diff --git a/renderdoc/os/win32/win32_threading.cpp b/renderdoc/os/win32/win32_threading.cpp index 988f78a4b..7e0df24a7 100644 --- a/renderdoc/os/win32/win32_threading.cpp +++ b/renderdoc/os/win32/win32_threading.cpp @@ -144,6 +144,21 @@ namespace Threading if(handle == 0) return; CloseHandle((HANDLE)handle); } + + static HMODULE ownModuleHandle = 0; + + void KeepModuleAlive() + { + // deliberately omitting GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT to bump refcount + GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (const char *)&ownModuleHandle, + &ownModuleHandle); + } + + void ReleaseModuleExitThread() + { + FreeLibraryAndExitThread(ownModuleHandle, 0); + } void Sleep(uint32_t milliseconds) {