|
|
@ -7,12 +7,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
#include "windows_crashmonitor.hpp"
|
|
|
|
#include "windows_crashmonitor.hpp"
|
|
|
|
#include "windows_crashshm.hpp"
|
|
|
|
#include "windows_crashshm.hpp"
|
|
|
|
|
|
|
|
#include "windowscrashdumppathhelpers.hpp"
|
|
|
|
#include <SDL_messagebox.h>
|
|
|
|
#include <SDL_messagebox.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include <components/misc/strings/conversion.hpp>
|
|
|
|
#include <components/misc/strings/conversion.hpp>
|
|
|
|
|
|
|
|
|
|
|
|
namespace Crash
|
|
|
|
namespace Crash
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
template <class T, std::size_t N>
|
|
|
|
|
|
|
|
void writePathToShm(T (&buffer)[N], const std::filesystem::path& path)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
memset(buffer, 0, sizeof(buffer));
|
|
|
|
|
|
|
|
const auto str = path.u8string();
|
|
|
|
|
|
|
|
size_t length = str.length();
|
|
|
|
|
|
|
|
if (length >= sizeof(buffer))
|
|
|
|
|
|
|
|
length = sizeof(buffer) - 1;
|
|
|
|
|
|
|
|
strncpy_s(buffer, sizeof(buffer), Misc::StringUtils::u8StringToString(str).c_str(), length);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HANDLE duplicateHandle(HANDLE handle)
|
|
|
|
HANDLE duplicateHandle(HANDLE handle)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -27,8 +41,8 @@ namespace Crash
|
|
|
|
|
|
|
|
|
|
|
|
CrashCatcher* CrashCatcher::sInstance = nullptr;
|
|
|
|
CrashCatcher* CrashCatcher::sInstance = nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
CrashCatcher::CrashCatcher(
|
|
|
|
CrashCatcher::CrashCatcher(int argc, char** argv, const std::filesystem::path& dumpPath,
|
|
|
|
int argc, char** argv, const std::filesystem::path& crashDumpPath, const std::filesystem::path& freezeDumpPath)
|
|
|
|
const std::filesystem::path& crashDumpName, const std::filesystem::path& freezeDumpName)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
assert(sInstance == nullptr); // don't allow two instances
|
|
|
|
assert(sInstance == nullptr); // don't allow two instances
|
|
|
|
|
|
|
|
|
|
|
@ -50,7 +64,7 @@ namespace Crash
|
|
|
|
if (!shmHandle)
|
|
|
|
if (!shmHandle)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
setupIpc();
|
|
|
|
setupIpc();
|
|
|
|
startMonitorProcess(crashDumpPath, freezeDumpPath);
|
|
|
|
startMonitorProcess(dumpPath, crashDumpName, freezeDumpName);
|
|
|
|
installHandler();
|
|
|
|
installHandler();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
@ -77,28 +91,22 @@ namespace Crash
|
|
|
|
CloseHandle(mShmHandle);
|
|
|
|
CloseHandle(mShmHandle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CrashCatcher::updateDumpPaths(
|
|
|
|
void CrashCatcher::updateDumpPath(const std::filesystem::path& dumpPath)
|
|
|
|
const std::filesystem::path& crashDumpPath, const std::filesystem::path& freezeDumpPath)
|
|
|
|
{
|
|
|
|
|
|
|
|
shmLock();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
writePathToShm(mShm->mStartup.mDumpDirectoryPath, dumpPath);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shmUnlock();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CrashCatcher::updateDumpNames(
|
|
|
|
|
|
|
|
const std::filesystem::path& crashDumpName, const std::filesystem::path& freezeDumpName)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
shmLock();
|
|
|
|
shmLock();
|
|
|
|
|
|
|
|
|
|
|
|
memset(mShm->mStartup.mCrashDumpFilePath, 0, sizeof(mShm->mStartup.mCrashDumpFilePath));
|
|
|
|
writePathToShm(mShm->mStartup.mCrashDumpFileName, crashDumpName);
|
|
|
|
const auto str = crashDumpPath.u8string();
|
|
|
|
writePathToShm(mShm->mStartup.mFreezeDumpFileName, freezeDumpName);
|
|
|
|
size_t length = str.length();
|
|
|
|
|
|
|
|
if (length >= MAX_LONG_PATH)
|
|
|
|
|
|
|
|
length = MAX_LONG_PATH - 1;
|
|
|
|
|
|
|
|
strncpy_s(mShm->mStartup.mCrashDumpFilePath, sizeof mShm->mStartup.mCrashDumpFilePath,
|
|
|
|
|
|
|
|
Misc::StringUtils::u8StringToString(str).c_str(), length);
|
|
|
|
|
|
|
|
mShm->mStartup.mCrashDumpFilePath[length] = '\0';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset(mShm->mStartup.mFreezeDumpFilePath, 0, sizeof(mShm->mStartup.mFreezeDumpFilePath));
|
|
|
|
|
|
|
|
const auto strFreeze = freezeDumpPath.u8string();
|
|
|
|
|
|
|
|
length = strFreeze.length();
|
|
|
|
|
|
|
|
if (length >= MAX_LONG_PATH)
|
|
|
|
|
|
|
|
length = MAX_LONG_PATH - 1;
|
|
|
|
|
|
|
|
strncpy_s(mShm->mStartup.mFreezeDumpFilePath, sizeof mShm->mStartup.mFreezeDumpFilePath,
|
|
|
|
|
|
|
|
Misc::StringUtils::u8StringToString(strFreeze).c_str(), length);
|
|
|
|
|
|
|
|
mShm->mStartup.mFreezeDumpFilePath[length] = '\0';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shmUnlock();
|
|
|
|
shmUnlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -153,8 +161,8 @@ namespace Crash
|
|
|
|
SetUnhandledExceptionFilter(vectoredExceptionHandler);
|
|
|
|
SetUnhandledExceptionFilter(vectoredExceptionHandler);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CrashCatcher::startMonitorProcess(
|
|
|
|
void CrashCatcher::startMonitorProcess(const std::filesystem::path& dumpPath,
|
|
|
|
const std::filesystem::path& crashDumpPath, const std::filesystem::path& freezeDumpPath)
|
|
|
|
const std::filesystem::path& crashDumpName, const std::filesystem::path& freezeDumpName)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::wstring executablePath;
|
|
|
|
std::wstring executablePath;
|
|
|
|
DWORD copied = 0;
|
|
|
|
DWORD copied = 0;
|
|
|
@ -165,23 +173,9 @@ namespace Crash
|
|
|
|
} while (copied >= executablePath.size());
|
|
|
|
} while (copied >= executablePath.size());
|
|
|
|
executablePath.resize(copied);
|
|
|
|
executablePath.resize(copied);
|
|
|
|
|
|
|
|
|
|
|
|
memset(mShm->mStartup.mCrashDumpFilePath, 0, sizeof(mShm->mStartup.mCrashDumpFilePath));
|
|
|
|
writePathToShm(mShm->mStartup.mDumpDirectoryPath, dumpPath);
|
|
|
|
const auto str = crashDumpPath.u8string();
|
|
|
|
writePathToShm(mShm->mStartup.mCrashDumpFileName, crashDumpName);
|
|
|
|
size_t length = str.length();
|
|
|
|
writePathToShm(mShm->mStartup.mFreezeDumpFileName, freezeDumpName);
|
|
|
|
if (length >= MAX_LONG_PATH)
|
|
|
|
|
|
|
|
length = MAX_LONG_PATH - 1;
|
|
|
|
|
|
|
|
strncpy_s(mShm->mStartup.mCrashDumpFilePath, sizeof mShm->mStartup.mCrashDumpFilePath,
|
|
|
|
|
|
|
|
Misc::StringUtils::u8StringToString(str).c_str(), length);
|
|
|
|
|
|
|
|
mShm->mStartup.mCrashDumpFilePath[length] = '\0';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset(mShm->mStartup.mFreezeDumpFilePath, 0, sizeof(mShm->mStartup.mFreezeDumpFilePath));
|
|
|
|
|
|
|
|
const auto strFreeze = freezeDumpPath.u8string();
|
|
|
|
|
|
|
|
length = strFreeze.length();
|
|
|
|
|
|
|
|
if (length >= MAX_LONG_PATH)
|
|
|
|
|
|
|
|
length = MAX_LONG_PATH - 1;
|
|
|
|
|
|
|
|
strncpy_s(mShm->mStartup.mFreezeDumpFilePath, sizeof mShm->mStartup.mFreezeDumpFilePath,
|
|
|
|
|
|
|
|
Misc::StringUtils::u8StringToString(strFreeze).c_str(), length);
|
|
|
|
|
|
|
|
mShm->mStartup.mFreezeDumpFilePath[length] = '\0';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// note that we don't need to lock the SHM here, the other process has not started yet
|
|
|
|
// note that we don't need to lock the SHM here, the other process has not started yet
|
|
|
|
mShm->mEvent = CrashSHM::Event::Startup;
|
|
|
|
mShm->mEvent = CrashSHM::Event::Startup;
|
|
|
@ -204,6 +198,9 @@ namespace Crash
|
|
|
|
if (!CreateProcessW(executablePath.data(), arguments.data(), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
|
|
|
|
if (!CreateProcessW(executablePath.data(), arguments.data(), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
|
|
|
|
throw std::runtime_error("Could not start crash monitor process");
|
|
|
|
throw std::runtime_error("Could not start crash monitor process");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CloseHandle(pi.hProcess);
|
|
|
|
|
|
|
|
CloseHandle(pi.hThread);
|
|
|
|
|
|
|
|
|
|
|
|
waitMonitor();
|
|
|
|
waitMonitor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -241,7 +238,7 @@ namespace Crash
|
|
|
|
waitMonitor();
|
|
|
|
waitMonitor();
|
|
|
|
|
|
|
|
|
|
|
|
std::string message = "OpenMW has encountered a fatal error.\nCrash log saved to '"
|
|
|
|
std::string message = "OpenMW has encountered a fatal error.\nCrash log saved to '"
|
|
|
|
+ std::string(mShm->mStartup.mCrashDumpFilePath)
|
|
|
|
+ Misc::StringUtils::u8StringToString(getCrashDumpPath(*mShm).u8string())
|
|
|
|
+ "'.\nPlease report this to https://gitlab.com/OpenMW/openmw/issues !";
|
|
|
|
+ "'.\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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|