mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-28 06:11:37 +00:00
Emit visible errors when crash dump creation fails
Also possibly fix the errors, as I was getting them when I started testing, and then wasn't by the time I'd got the code how I wanted it. However, nothing in this commit looks like it *should* fix any errors.
This commit is contained in:
parent
1c242425b0
commit
9010a5bb32
3 changed files with 83 additions and 9 deletions
|
@ -129,6 +129,8 @@ namespace Crash
|
||||||
if (mShm == nullptr)
|
if (mShm == nullptr)
|
||||||
throw std::runtime_error("Failed to map crash catcher shared memory");
|
throw std::runtime_error("Failed to map crash catcher shared memory");
|
||||||
|
|
||||||
|
mShm->mMonitorStatus = CrashSHM::Status::Uninitialised;
|
||||||
|
|
||||||
mShmMutex = CreateMutexW(&attributes, FALSE, NULL);
|
mShmMutex = CreateMutexW(&attributes, FALSE, NULL);
|
||||||
if (mShmMutex == nullptr)
|
if (mShmMutex == nullptr)
|
||||||
throw std::runtime_error("Failed to create crash catcher shared memory mutex");
|
throw std::runtime_error("Failed to create crash catcher shared memory mutex");
|
||||||
|
@ -234,13 +236,31 @@ namespace Crash
|
||||||
|
|
||||||
signalMonitor();
|
signalMonitor();
|
||||||
|
|
||||||
// must remain until monitor has finished
|
try
|
||||||
waitMonitor();
|
{
|
||||||
|
// give monitor a chance to start dumping
|
||||||
|
// do this in try/catch as dumping might take longer than the timeout and an exception will be thrown when
|
||||||
|
// we're resumed
|
||||||
|
waitMonitor();
|
||||||
|
}
|
||||||
|
catch (std::exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
std::string message = "OpenMW has encountered a fatal error.\nCrash dump saved to '"
|
shmLock();
|
||||||
+ Misc::StringUtils::u8StringToString(getCrashDumpPath(*mShm).u8string())
|
CrashSHM::Status monitorStatus = mShm->mMonitorStatus;
|
||||||
+ "'.\nPlease report this to https://gitlab.com/OpenMW/openmw/issues !";
|
shmUnlock();
|
||||||
SDL_ShowSimpleMessageBox(0, "Fatal Error", message.c_str(), nullptr);
|
|
||||||
|
if (monitorStatus == CrashSHM::Status::DumpedSuccessfully)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string message = "OpenMW has encountered a fatal error.\nCrash dump saved to '"
|
||||||
|
+ Misc::StringUtils::u8StringToString(getCrashDumpPath(*mShm).u8string())
|
||||||
|
+ "'.\nPlease report this to https://gitlab.com/OpenMW/openmw/issues !";
|
||||||
|
SDL_ShowSimpleMessageBox(0, "Fatal Error", message.c_str(), nullptr);
|
||||||
|
}
|
||||||
|
else if (monitorStatus == CrashSHM::Status::Dumping)
|
||||||
|
SDL_ShowSimpleMessageBox(0, "Fatal Error", "Timed out while creating crash dump", nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Crash
|
} // namespace Crash
|
||||||
|
|
|
@ -163,6 +163,7 @@ namespace Crash
|
||||||
|
|
||||||
void CrashMonitor::run()
|
void CrashMonitor::run()
|
||||||
{
|
{
|
||||||
|
mShm->mMonitorStatus = CrashSHM::Status::Monitoring;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// app waits for monitor start up, let it continue
|
// app waits for monitor start up, let it continue
|
||||||
|
@ -231,6 +232,18 @@ namespace Crash
|
||||||
|
|
||||||
void CrashMonitor::handleCrash(bool isFreeze)
|
void CrashMonitor::handleCrash(bool isFreeze)
|
||||||
{
|
{
|
||||||
|
shmLock();
|
||||||
|
mShm->mMonitorStatus = CrashSHM::Status::Dumping;
|
||||||
|
shmUnlock();
|
||||||
|
|
||||||
|
auto failedDumping = [this](const std::string& message) {
|
||||||
|
Log(Debug::Error) << "CrashMonitor: " << message;
|
||||||
|
shmLock();
|
||||||
|
mShm->mMonitorStatus = CrashSHM::Status::FailedDumping;
|
||||||
|
shmUnlock();
|
||||||
|
SDL_ShowSimpleMessageBox(0, "Failed to create crash dump", message.c_str(), nullptr);
|
||||||
|
};
|
||||||
|
|
||||||
DWORD processId = GetProcessId(mAppProcessHandle);
|
DWORD processId = GetProcessId(mAppProcessHandle);
|
||||||
const char* env = getenv("OPENMW_FULL_MEMDUMP");
|
const char* env = getenv("OPENMW_FULL_MEMDUMP");
|
||||||
|
|
||||||
|
@ -238,7 +251,10 @@ namespace Crash
|
||||||
{
|
{
|
||||||
HMODULE dbghelp = LoadLibraryA("dbghelp.dll");
|
HMODULE dbghelp = LoadLibraryA("dbghelp.dll");
|
||||||
if (dbghelp == NULL)
|
if (dbghelp == NULL)
|
||||||
|
{
|
||||||
|
failedDumping("Could not load dbghelp.dll");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
using MiniDumpWirteDumpFn = BOOL(WINAPI*)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
|
using MiniDumpWirteDumpFn = BOOL(WINAPI*)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
|
||||||
MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
||||||
|
@ -246,11 +262,17 @@ namespace Crash
|
||||||
|
|
||||||
MiniDumpWirteDumpFn miniDumpWriteDump = (MiniDumpWirteDumpFn)GetProcAddress(dbghelp, "MiniDumpWriteDump");
|
MiniDumpWirteDumpFn miniDumpWriteDump = (MiniDumpWirteDumpFn)GetProcAddress(dbghelp, "MiniDumpWriteDump");
|
||||||
if (miniDumpWriteDump == NULL)
|
if (miniDumpWriteDump == NULL)
|
||||||
|
{
|
||||||
|
failedDumping("Could not get MiniDumpWriteDump address");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::wstring utf16Path = (isFreeze ? getFreezeDumpPath(*mShm) : getCrashDumpPath(*mShm)).native();
|
std::wstring utf16Path = (isFreeze ? getFreezeDumpPath(*mShm) : getCrashDumpPath(*mShm)).native();
|
||||||
if (utf16Path.empty())
|
if (utf16Path.empty())
|
||||||
|
{
|
||||||
|
failedDumping("Empty dump path");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (utf16Path.length() > MAX_PATH)
|
if (utf16Path.length() > MAX_PATH)
|
||||||
utf16Path = LR"(\\?\)" + utf16Path;
|
utf16Path = LR"(\\?\)" + utf16Path;
|
||||||
|
@ -258,9 +280,17 @@ namespace Crash
|
||||||
HANDLE hCrashLog = CreateFileW(utf16Path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
|
HANDLE hCrashLog = CreateFileW(utf16Path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
|
||||||
FILE_ATTRIBUTE_NORMAL, nullptr);
|
FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
if (hCrashLog == NULL || hCrashLog == INVALID_HANDLE_VALUE)
|
if (hCrashLog == NULL || hCrashLog == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
failedDumping("Bad dump file handle");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (auto err = GetLastError(); err != ERROR_ALREADY_EXISTS && err != 0)
|
if (auto err = GetLastError(); err != ERROR_ALREADY_EXISTS && err != 0)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "Error opening dump file: " << std::hex << err;
|
||||||
|
failedDumping(ss.str());
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
EXCEPTION_POINTERS exp;
|
EXCEPTION_POINTERS exp;
|
||||||
exp.ContextRecord = &mShm->mCrashed.mContext;
|
exp.ContextRecord = &mShm->mCrashed.mContext;
|
||||||
|
@ -274,15 +304,28 @@ namespace Crash
|
||||||
if (env)
|
if (env)
|
||||||
type = static_cast<MINIDUMP_TYPE>(type | MiniDumpWithFullMemory);
|
type = static_cast<MINIDUMP_TYPE>(type | MiniDumpWithFullMemory);
|
||||||
|
|
||||||
miniDumpWriteDump(mAppProcessHandle, processId, hCrashLog, type, &infos, 0, 0);
|
if (!miniDumpWriteDump(mAppProcessHandle, processId, hCrashLog, type, &infos, 0, 0))
|
||||||
|
{
|
||||||
|
auto err = GetLastError();
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "Error while writing dump: " << std::hex << err;
|
||||||
|
failedDumping(ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shmLock();
|
||||||
|
mShm->mMonitorStatus = CrashSHM::Status::DumpedSuccessfully;
|
||||||
|
shmUnlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
Log(Debug::Error) << "CrashMonitor: " << e.what();
|
failedDumping(e.what());
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
Log(Debug::Error) << "CrashMonitor: unknown exception";
|
failedDumping("Unknown exception");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,17 @@ namespace Crash
|
||||||
|
|
||||||
Event mEvent;
|
Event mEvent;
|
||||||
|
|
||||||
|
enum class Status
|
||||||
|
{
|
||||||
|
Uninitialised,
|
||||||
|
Monitoring,
|
||||||
|
Dumping,
|
||||||
|
DumpedSuccessfully,
|
||||||
|
FailedDumping
|
||||||
|
};
|
||||||
|
|
||||||
|
Status mMonitorStatus;
|
||||||
|
|
||||||
struct Startup
|
struct Startup
|
||||||
{
|
{
|
||||||
HANDLE mAppProcessHandle;
|
HANDLE mAppProcessHandle;
|
||||||
|
|
Loading…
Reference in a new issue