mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-09 21:44:54 +00:00
Attempt to catch freezes on Windows
This commit is contained in:
parent
46564f08ad
commit
c746a8abb7
@ -144,6 +144,7 @@ namespace Crash
|
|||||||
mShm->mEvent = CrashSHM::Event::Startup;
|
mShm->mEvent = CrashSHM::Event::Startup;
|
||||||
mShm->mStartup.mShmMutex = duplicateHandle(mShmMutex);
|
mShm->mStartup.mShmMutex = duplicateHandle(mShmMutex);
|
||||||
mShm->mStartup.mAppProcessHandle = duplicateHandle(GetCurrentProcess());
|
mShm->mStartup.mAppProcessHandle = duplicateHandle(GetCurrentProcess());
|
||||||
|
mShm->mStartup.mAppMainThreadId = GetThreadId(GetCurrentThread());
|
||||||
mShm->mStartup.mSignalApp = duplicateHandle(mSignalAppEvent);
|
mShm->mStartup.mSignalApp = duplicateHandle(mSignalAppEvent);
|
||||||
mShm->mStartup.mSignalMonitor = duplicateHandle(mSignalMonitorEvent);
|
mShm->mStartup.mSignalMonitor = duplicateHandle(mSignalMonitorEvent);
|
||||||
|
|
||||||
@ -196,7 +197,7 @@ namespace Crash
|
|||||||
// must remain until monitor has finished
|
// must remain until monitor has finished
|
||||||
waitMonitor();
|
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);
|
SDL_ShowSimpleMessageBox(0, "Fatal Error", message.c_str(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <SDL_messagebox.h>
|
||||||
|
|
||||||
#include "windows_crashcatcher.hpp"
|
#include "windows_crashcatcher.hpp"
|
||||||
#include "windows_crashmonitor.hpp"
|
#include "windows_crashmonitor.hpp"
|
||||||
#include "windows_crashshm.hpp"
|
#include "windows_crashshm.hpp"
|
||||||
@ -28,6 +30,7 @@ namespace Crash
|
|||||||
|
|
||||||
mShmMutex = mShm->mStartup.mShmMutex;
|
mShmMutex = mShm->mStartup.mShmMutex;
|
||||||
mAppProcessHandle = mShm->mStartup.mAppProcessHandle;
|
mAppProcessHandle = mShm->mStartup.mAppProcessHandle;
|
||||||
|
mAppMainThreadId = mShm->mStartup.mAppMainThreadId;
|
||||||
mSignalAppEvent = mShm->mStartup.mSignalApp;
|
mSignalAppEvent = mShm->mStartup.mSignalApp;
|
||||||
mSignalMonitorEvent = mShm->mStartup.mSignalMonitor;
|
mSignalMonitorEvent = mShm->mStartup.mSignalMonitor;
|
||||||
}
|
}
|
||||||
@ -80,6 +83,44 @@ namespace Crash
|
|||||||
return code == STILL_ACTIVE;
|
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()
|
void CrashMonitor::run()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -88,8 +129,16 @@ namespace Crash
|
|||||||
signalApp();
|
signalApp();
|
||||||
|
|
||||||
bool running = true;
|
bool running = true;
|
||||||
|
bool frozen = false;
|
||||||
while (isAppAlive() && running)
|
while (isAppAlive() && running)
|
||||||
{
|
{
|
||||||
|
if (isAppFrozen())
|
||||||
|
{
|
||||||
|
frozen = true;
|
||||||
|
handleCrash();
|
||||||
|
running = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (waitApp())
|
if (waitApp())
|
||||||
{
|
{
|
||||||
shmLock();
|
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 (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
HANDLE mAppProcessHandle = nullptr;
|
HANDLE mAppProcessHandle = nullptr;
|
||||||
|
DWORD mAppMainThreadId = 0;
|
||||||
|
HWND mAppWindowHandle = nullptr;
|
||||||
|
|
||||||
// triggered when the monitor process wants to wake the parent process (received via SHM)
|
// triggered when the monitor process wants to wake the parent process (received via SHM)
|
||||||
HANDLE mSignalAppEvent = nullptr;
|
HANDLE mSignalAppEvent = nullptr;
|
||||||
@ -37,6 +39,8 @@ private:
|
|||||||
|
|
||||||
bool isAppAlive() const;
|
bool isAppAlive() const;
|
||||||
|
|
||||||
|
bool isAppFrozen();
|
||||||
|
|
||||||
void shmLock();
|
void shmLock();
|
||||||
|
|
||||||
void shmUnlock();
|
void shmUnlock();
|
||||||
|
@ -26,6 +26,7 @@ namespace Crash
|
|||||||
struct Startup
|
struct Startup
|
||||||
{
|
{
|
||||||
HANDLE mAppProcessHandle;
|
HANDLE mAppProcessHandle;
|
||||||
|
DWORD mAppMainThreadId;
|
||||||
HANDLE mSignalApp;
|
HANDLE mSignalApp;
|
||||||
HANDLE mSignalMonitor;
|
HANDLE mSignalMonitor;
|
||||||
HANDLE mShmMutex;
|
HANDLE mShmMutex;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user