- Make sure a hung worker thread always crashes the application

This commit is contained in:
Magnus Norddahl 2017-05-21 12:03:12 +02:00
parent aff9205057
commit e27e89b57d
3 changed files with 38 additions and 2 deletions

View file

@ -33,6 +33,11 @@
#include "r_thread.h" #include "r_thread.h"
#include "swrenderer/r_memory.h" #include "swrenderer/r_memory.h"
#include "swrenderer/r_renderthread.h" #include "swrenderer/r_renderthread.h"
#include <chrono>
#ifdef WIN32
void PeekThreadedErrorPane();
#endif
CVAR(Bool, r_multithreaded, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); CVAR(Bool, r_multithreaded, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
@ -73,10 +78,20 @@ void DrawerThreads::Execute(DrawerCommandQueuePtr commands)
void DrawerThreads::WaitForWorkers() void DrawerThreads::WaitForWorkers()
{ {
using namespace std::chrono_literals;
// Wait for workers to finish // Wait for workers to finish
auto queue = Instance(); auto queue = Instance();
std::unique_lock<std::mutex> end_lock(queue->end_mutex); std::unique_lock<std::mutex> end_lock(queue->end_mutex);
queue->end_condition.wait(end_lock, [&]() { return queue->tasks_left == 0; }); if (!queue->end_condition.wait_for(end_lock, 5s, [&]() { return queue->tasks_left == 0; }))
{
#ifdef WIN32
PeekThreadedErrorPane();
#endif
// Invoke the crash reporter so that we can capture the call stack of whatever the hung worker thread is doing
int *threadCrashed = nullptr;
*threadCrashed = 0xdeadbeef;
}
end_lock.unlock(); end_lock.unlock();
// Clean up // Clean up

View file

@ -57,6 +57,11 @@
#include "swrenderer/r_memory.h" #include "swrenderer/r_memory.h"
#include "swrenderer/r_renderthread.h" #include "swrenderer/r_renderthread.h"
#include "swrenderer/things/r_playersprite.h" #include "swrenderer/things/r_playersprite.h"
#include <chrono>
#ifdef WIN32
void PeekThreadedErrorPane();
#endif
EXTERN_CVAR(Bool, r_shadercolormaps) EXTERN_CVAR(Bool, r_shadercolormaps)
EXTERN_CVAR(Int, r_clearbuffer) EXTERN_CVAR(Int, r_clearbuffer)
@ -217,9 +222,18 @@ namespace swrenderer
// Wait for everyone to finish: // Wait for everyone to finish:
if (Threads.size() > 1) if (Threads.size() > 1)
{ {
using namespace std::chrono_literals;
std::unique_lock<std::mutex> end_lock(end_mutex); std::unique_lock<std::mutex> end_lock(end_mutex);
finished_threads++; finished_threads++;
end_condition.wait(end_lock, [&]() { return finished_threads == Threads.size(); }); if (!end_condition.wait_for(end_lock, 5s, [&]() { return finished_threads == Threads.size(); }))
{
#ifdef WIN32
PeekThreadedErrorPane();
#endif
// Invoke the crash reporter so that we can capture the call stack of whatever the hung worker thread is doing
int *threadCrashed = nullptr;
*threadCrashed = 0xdeadbeef;
}
finished_threads = 0; finished_threads = 0;
} }

View file

@ -821,6 +821,13 @@ void ShowErrorPane(const char *text)
} }
} }
void PeekThreadedErrorPane()
{
// Allow SendMessage from another thread to call its message handler so that it can display the crash dialog
MSG msg;
PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
}
//========================================================================== //==========================================================================
// //
// DoMain // DoMain