Attempt to catch freezes on Windows

librecast_all_the_things
AnyOldName3 3 years ago
parent 46564f08ad
commit c746a8abb7

@ -144,6 +144,7 @@ namespace Crash
mShm->mEvent = CrashSHM::Event::Startup;
mShm->mStartup.mShmMutex = duplicateHandle(mShmMutex);
mShm->mStartup.mAppProcessHandle = duplicateHandle(GetCurrentProcess());
mShm->mStartup.mAppMainThreadId = GetThreadId(GetCurrentThread());
mShm->mStartup.mSignalApp = duplicateHandle(mSignalAppEvent);
mShm->mStartup.mSignalMonitor = duplicateHandle(mSignalMonitorEvent);
@ -196,7 +197,7 @@ namespace Crash
// must remain until monitor has finished
waitMonitor();
std::string message = "OpenMW has encountered a fatal error.\nCrash log saved to '" + std::string(mShm->mStartup.mLogFilePath) + "'.\n Please report this to https://gitlab.com/OpenMW/openmw/issues !";
std::string message = "OpenMW has encountered a fatal error.\nCrash log saved to '" + std::string(mShm->mStartup.mLogFilePath) + "'.\nPlease report this to https://gitlab.com/OpenMW/openmw/issues !";
SDL_ShowSimpleMessageBox(0, "Fatal Error", message.c_str(), nullptr);
}

@ -9,6 +9,8 @@
#include <memory>
#include <sstream>
#include <SDL_messagebox.h>
#include "windows_crashcatcher.hpp"
#include "windows_crashmonitor.hpp"
#include "windows_crashshm.hpp"
@ -28,6 +30,7 @@ namespace Crash
mShmMutex = mShm->mStartup.mShmMutex;
mAppProcessHandle = mShm->mStartup.mAppProcessHandle;
mAppMainThreadId = mShm->mStartup.mAppMainThreadId;
mSignalAppEvent = mShm->mStartup.mSignalApp;
mSignalMonitorEvent = mShm->mStartup.mSignalMonitor;
}
@ -80,6 +83,44 @@ namespace Crash
return code == STILL_ACTIVE;
}
bool CrashMonitor::isAppFrozen()
{
if (!mAppWindowHandle)
{
EnumWindows([](HWND handle, LPARAM param) -> BOOL {
CrashMonitor& crashMonitor = *(CrashMonitor*)param;
DWORD processId;
if (GetWindowThreadProcessId(handle, &processId) == crashMonitor.mAppMainThreadId && processId == GetProcessId(crashMonitor.mAppProcessHandle))
{
if (GetWindow(handle, GW_OWNER) == 0)
{
crashMonitor.mAppWindowHandle = handle;
return false;
}
}
return true;
}, (LPARAM)this);
if (mAppWindowHandle)
{
// TODO: use https://devblogs.microsoft.com/oldnewthing/20111026-00/?p=9263 to monitor for the window being destroyed
}
else
return false;
}
if (IsHungAppWindow)
return IsHungAppWindow(mAppWindowHandle);
else
{
BOOL debuggerPresent;
if (CheckRemoteDebuggerPresent(mAppProcessHandle, &debuggerPresent) && debuggerPresent)
return false;
if (SendMessageTimeoutA(mAppWindowHandle, WM_NULL, 0, 0, 0, 5000, nullptr) == 0)
return GetLastError() == ERROR_TIMEOUT;
}
return false;
}
void CrashMonitor::run()
{
try
@ -88,8 +129,16 @@ namespace Crash
signalApp();
bool running = true;
bool frozen = false;
while (isAppAlive() && running)
{
if (isAppFrozen())
{
frozen = true;
handleCrash();
running = false;
break;
}
if (waitApp())
{
shmLock();
@ -113,6 +162,13 @@ namespace Crash
}
}
if (frozen)
{
TerminateProcess(mAppProcessHandle, -1);
std::string message = "OpenMW appears to have frozen.\nCrash log saved to '" + std::string(mShm->mStartup.mLogFilePath) + "'.\nPlease report this to https://gitlab.com/OpenMW/openmw/issues !";
SDL_ShowSimpleMessageBox(0, "Fatal Error", message.c_str(), nullptr);
}
}
catch (...)
{

@ -21,6 +21,8 @@ public:
private:
HANDLE mAppProcessHandle = nullptr;
DWORD mAppMainThreadId = 0;
HWND mAppWindowHandle = nullptr;
// triggered when the monitor process wants to wake the parent process (received via SHM)
HANDLE mSignalAppEvent = nullptr;
@ -37,6 +39,8 @@ private:
bool isAppAlive() const;
bool isAppFrozen();
void shmLock();
void shmUnlock();

@ -26,6 +26,7 @@ namespace Crash
struct Startup
{
HANDLE mAppProcessHandle;
DWORD mAppMainThreadId;
HANDLE mSignalApp;
HANDLE mSignalMonitor;
HANDLE mShmMutex;

Loading…
Cancel
Save