1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-06-27 10:41:34 +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:
AnyOldName3 2025-06-09 00:20:58 +01:00
parent 1c242425b0
commit 9010a5bb32
3 changed files with 83 additions and 9 deletions

View file

@ -129,6 +129,8 @@ namespace Crash
if (mShm == nullptr)
throw std::runtime_error("Failed to map crash catcher shared memory");
mShm->mMonitorStatus = CrashSHM::Status::Uninitialised;
mShmMutex = CreateMutexW(&attributes, FALSE, NULL);
if (mShmMutex == nullptr)
throw std::runtime_error("Failed to create crash catcher shared memory mutex");
@ -234,13 +236,31 @@ namespace Crash
signalMonitor();
// must remain until monitor has finished
waitMonitor();
try
{
// 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 '"
+ 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);
shmLock();
CrashSHM::Status monitorStatus = mShm->mMonitorStatus;
shmUnlock();
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

View file

@ -163,6 +163,7 @@ namespace Crash
void CrashMonitor::run()
{
mShm->mMonitorStatus = CrashSHM::Status::Monitoring;
try
{
// app waits for monitor start up, let it continue
@ -231,6 +232,18 @@ namespace Crash
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);
const char* env = getenv("OPENMW_FULL_MEMDUMP");
@ -238,7 +251,10 @@ namespace Crash
{
HMODULE dbghelp = LoadLibraryA("dbghelp.dll");
if (dbghelp == NULL)
{
failedDumping("Could not load dbghelp.dll");
return;
}
using MiniDumpWirteDumpFn = BOOL(WINAPI*)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
@ -246,11 +262,17 @@ namespace Crash
MiniDumpWirteDumpFn miniDumpWriteDump = (MiniDumpWirteDumpFn)GetProcAddress(dbghelp, "MiniDumpWriteDump");
if (miniDumpWriteDump == NULL)
{
failedDumping("Could not get MiniDumpWriteDump address");
return;
}
std::wstring utf16Path = (isFreeze ? getFreezeDumpPath(*mShm) : getCrashDumpPath(*mShm)).native();
if (utf16Path.empty())
{
failedDumping("Empty dump path");
return;
}
if (utf16Path.length() > MAX_PATH)
utf16Path = LR"(\\?\)" + utf16Path;
@ -258,9 +280,17 @@ namespace Crash
HANDLE hCrashLog = CreateFileW(utf16Path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (hCrashLog == NULL || hCrashLog == INVALID_HANDLE_VALUE)
{
failedDumping("Bad dump file handle");
return;
}
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;
}
EXCEPTION_POINTERS exp;
exp.ContextRecord = &mShm->mCrashed.mContext;
@ -274,15 +304,28 @@ namespace Crash
if (env)
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)
{
Log(Debug::Error) << "CrashMonitor: " << e.what();
failedDumping(e.what());
}
catch (...)
{
Log(Debug::Error) << "CrashMonitor: unknown exception";
failedDumping("Unknown exception");
}
}

View file

@ -22,6 +22,17 @@ namespace Crash
Event mEvent;
enum class Status
{
Uninitialised,
Monitoring,
Dumping,
DumpedSuccessfully,
FailedDumping
};
Status mMonitorStatus;
struct Startup
{
HANDLE mAppProcessHandle;