mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-31 19:45:34 +00:00
Share the dump directory for crash and freeze dumps
This means the shared memory struct is just 255 bytes longer than a few commits ago instead of 32K. Also introduce a function for putting path strings in the shared memory as there was too much copied and pasted code and it was error-prone. Also free some handles once we're done with them so they don't leak. Manual port of https://gitlab.com/OpenMW/openmw/-/merge_requests/3221 to OpenMW 0.48
This commit is contained in:
parent
0a593c4741
commit
33884dba30
8 changed files with 75 additions and 37 deletions
|
@ -284,6 +284,7 @@ if(WIN32)
|
||||||
windows_crashcatcher
|
windows_crashcatcher
|
||||||
windows_crashmonitor
|
windows_crashmonitor
|
||||||
windows_crashshm
|
windows_crashshm
|
||||||
|
windowscrashdumppathhelpers
|
||||||
)
|
)
|
||||||
elseif(NOT ANDROID)
|
elseif(NOT ANDROID)
|
||||||
add_component_dir (crashcatcher
|
add_component_dir (crashcatcher
|
||||||
|
|
|
@ -7,10 +7,23 @@
|
||||||
|
|
||||||
#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>
|
||||||
|
|
||||||
namespace Crash
|
namespace Crash
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template <class T, std::size_t N>
|
||||||
|
void writePathToShm(T(&buffer)[N], const std::string& path)
|
||||||
|
{
|
||||||
|
memset(buffer, 0, sizeof(buffer));
|
||||||
|
size_t length = path.length();
|
||||||
|
if (length >= sizeof(buffer))
|
||||||
|
length = sizeof(buffer) - 1;
|
||||||
|
strncpy(buffer, path.c_str(), length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HANDLE duplicateHandle(HANDLE handle)
|
HANDLE duplicateHandle(HANDLE handle)
|
||||||
{
|
{
|
||||||
|
@ -26,7 +39,7 @@ namespace Crash
|
||||||
|
|
||||||
CrashCatcher* CrashCatcher::sInstance = nullptr;
|
CrashCatcher* CrashCatcher::sInstance = nullptr;
|
||||||
|
|
||||||
CrashCatcher::CrashCatcher(int argc, char** argv, const std::string& crashDumpPath, const std::string& freezeDumpPath)
|
CrashCatcher::CrashCatcher(int argc, char** argv, const std::string& dumpPath, const std::string& crashDumpName, const std::string& freezeDumpName)
|
||||||
{
|
{
|
||||||
assert(sInstance == nullptr); // don't allow two instances
|
assert(sInstance == nullptr); // don't allow two instances
|
||||||
|
|
||||||
|
@ -48,7 +61,7 @@ namespace Crash
|
||||||
if (!shmHandle)
|
if (!shmHandle)
|
||||||
{
|
{
|
||||||
setupIpc();
|
setupIpc();
|
||||||
startMonitorProcess(crashDumpPath, freezeDumpPath);
|
startMonitorProcess(dumpPath, crashDumpName, freezeDumpName);
|
||||||
installHandler();
|
installHandler();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -75,21 +88,21 @@ namespace Crash
|
||||||
CloseHandle(mShmHandle);
|
CloseHandle(mShmHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrashCatcher::updateDumpPaths(const std::string& crashDumpPath, const std::string& freezeDumpPath)
|
void CrashCatcher::updateDumpPath(const std::string& dumpPath)
|
||||||
{
|
{
|
||||||
shmLock();
|
shmLock();
|
||||||
|
|
||||||
memset(mShm->mStartup.mCrashDumpFilePath, 0, sizeof(mShm->mStartup.mCrashDumpFilePath));
|
writePathToShm(mShm->mStartup.mDumpDirectoryPath, dumpPath);
|
||||||
size_t length = crashDumpPath.length();
|
|
||||||
if (length >= MAX_LONG_PATH) length = MAX_LONG_PATH - 1;
|
|
||||||
strncpy(mShm->mStartup.mCrashDumpFilePath, crashDumpPath.c_str(), length);
|
|
||||||
mShm->mStartup.mCrashDumpFilePath[length] = '\0';
|
|
||||||
|
|
||||||
memset(mShm->mStartup.mFreezeDumpFilePath, 0, sizeof(mShm->mStartup.mFreezeDumpFilePath));
|
shmUnlock();
|
||||||
length = freezeDumpPath.length();
|
}
|
||||||
if (length >= MAX_LONG_PATH) length = MAX_LONG_PATH - 1;
|
|
||||||
strncpy(mShm->mStartup.mFreezeDumpFilePath, freezeDumpPath.c_str(), length);
|
void CrashCatcher::updateDumpNames(const std::string& crashDumpName, const std::string& freezeDumpName)
|
||||||
mShm->mStartup.mFreezeDumpFilePath[length] = '\0';
|
{
|
||||||
|
shmLock();
|
||||||
|
|
||||||
|
writePathToShm(mShm->mStartup.mCrashDumpFileName, crashDumpName);
|
||||||
|
writePathToShm(mShm->mStartup.mFreezeDumpFileName, freezeDumpName);
|
||||||
|
|
||||||
shmUnlock();
|
shmUnlock();
|
||||||
}
|
}
|
||||||
|
@ -143,7 +156,7 @@ namespace Crash
|
||||||
SetUnhandledExceptionFilter(vectoredExceptionHandler);
|
SetUnhandledExceptionFilter(vectoredExceptionHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrashCatcher::startMonitorProcess(const std::string& crashDumpPath, const std::string& freezeDumpPath)
|
void CrashCatcher::startMonitorProcess(const std::string& dumpPath, const std::string& crashDumpName, const std::string& freezeDumpName)
|
||||||
{
|
{
|
||||||
std::wstring executablePath;
|
std::wstring executablePath;
|
||||||
DWORD copied = 0;
|
DWORD copied = 0;
|
||||||
|
@ -153,17 +166,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);
|
||||||
size_t length = crashDumpPath.length();
|
writePathToShm(mShm->mStartup.mCrashDumpFileName, crashDumpName);
|
||||||
if (length >= MAX_LONG_PATH) length = MAX_LONG_PATH - 1;
|
writePathToShm(mShm->mStartup.mFreezeDumpFileName, freezeDumpName);
|
||||||
strncpy(mShm->mStartup.mCrashDumpFilePath, crashDumpPath.c_str(), length);
|
|
||||||
mShm->mStartup.mCrashDumpFilePath[length] = '\0';
|
|
||||||
|
|
||||||
memset(mShm->mStartup.mFreezeDumpFilePath, 0, sizeof(mShm->mStartup.mFreezeDumpFilePath));
|
|
||||||
length = freezeDumpPath.length();
|
|
||||||
if (length >= MAX_LONG_PATH) length = MAX_LONG_PATH - 1;
|
|
||||||
strncpy(mShm->mStartup.mFreezeDumpFilePath, freezeDumpPath.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;
|
||||||
|
@ -186,6 +191,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +230,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.mCrashDumpFilePath) + "'.\nPlease report this to https://gitlab.com/OpenMW/openmw/issues !";
|
std::string message = "OpenMW has encountered a fatal error.\nCrash log saved to '" + getCrashDumpPath(*mShm) + "'.\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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,12 @@ namespace Crash
|
||||||
return sInstance;
|
return sInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
CrashCatcher(int argc, char** argv, const std::string& crashDumpPath, const std::string& freezeDumpPath);
|
CrashCatcher(int argc, char** argv, const std::string& dumpPath, const std::string& crashDumpName, const std::string& freezeDumpName);
|
||||||
~CrashCatcher();
|
~CrashCatcher();
|
||||||
|
|
||||||
void updateDumpPaths(const std::string& crashDumpPath, const std::string& freezeDumpPath);
|
void updateDumpPath(const std::string& dumpPath);
|
||||||
|
|
||||||
|
void updateDumpNames(const std::string& crashDumpName, const std::string& freezeDumpName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -62,7 +64,7 @@ namespace Crash
|
||||||
|
|
||||||
void shmUnlock();
|
void shmUnlock();
|
||||||
|
|
||||||
void startMonitorProcess(const std::string& crashDumpPath, const std::string& freezeDumpPath);
|
void startMonitorProcess(const std::string& dumpPath, const std::string& crashDumpName, const std::string& freezeDumpName);
|
||||||
|
|
||||||
void waitMonitor();
|
void waitMonitor();
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "windows_crashcatcher.hpp"
|
#include "windows_crashcatcher.hpp"
|
||||||
#include "windows_crashshm.hpp"
|
#include "windows_crashshm.hpp"
|
||||||
|
#include "windowscrashdumppathhelpers.hpp"
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
namespace Crash
|
namespace Crash
|
||||||
|
@ -207,7 +208,7 @@ namespace Crash
|
||||||
{
|
{
|
||||||
handleCrash(true);
|
handleCrash(true);
|
||||||
TerminateProcess(mAppProcessHandle, 0xDEAD);
|
TerminateProcess(mAppProcessHandle, 0xDEAD);
|
||||||
std::string message = "OpenMW appears to have frozen.\nCrash log saved to '" + std::string(mShm->mStartup.mFreezeDumpFilePath) + "'.\nPlease report this to https://gitlab.com/OpenMW/openmw/issues !";
|
std::string message = "OpenMW appears to have frozen.\nCrash log saved to '" + getFreezeDumpPath(*mShm) + "'.\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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +251,7 @@ namespace Crash
|
||||||
if (miniDumpWriteDump == NULL)
|
if (miniDumpWriteDump == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::wstring utf16Path = utf8ToUtf16(isFreeze ? mShm->mStartup.mFreezeDumpFilePath : mShm->mStartup.mCrashDumpFilePath);
|
std::wstring utf16Path = utf8ToUtf16(isFreeze ? getFreezeDumpPath(*mShm) : getCrashDumpPath(*mShm));
|
||||||
if (utf16Path.empty())
|
if (utf16Path.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ namespace Crash
|
||||||
|
|
||||||
// Used to communicate between the app and the monitor, fields are is overwritten with each event.
|
// Used to communicate between the app and the monitor, fields are is overwritten with each event.
|
||||||
static constexpr const int MAX_LONG_PATH = 0x7fff;
|
static constexpr const int MAX_LONG_PATH = 0x7fff;
|
||||||
|
static constexpr const int MAX_FILENAME = 0xff;
|
||||||
|
|
||||||
struct CrashSHM
|
struct CrashSHM
|
||||||
{
|
{
|
||||||
|
@ -28,8 +29,9 @@ namespace Crash
|
||||||
HANDLE mSignalApp;
|
HANDLE mSignalApp;
|
||||||
HANDLE mSignalMonitor;
|
HANDLE mSignalMonitor;
|
||||||
HANDLE mShmMutex;
|
HANDLE mShmMutex;
|
||||||
char mCrashDumpFilePath[MAX_LONG_PATH];
|
char mDumpDirectoryPath[MAX_LONG_PATH];
|
||||||
char mFreezeDumpFilePath[MAX_LONG_PATH];
|
char mCrashDumpFileName[MAX_FILENAME];
|
||||||
|
char mFreezeDumpFileName[MAX_FILENAME];
|
||||||
} mStartup;
|
} mStartup;
|
||||||
|
|
||||||
struct Crashed
|
struct Crashed
|
||||||
|
|
13
components/crashcatcher/windowscrashdumppathhelpers.cpp
Normal file
13
components/crashcatcher/windowscrashdumppathhelpers.cpp
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#include "windowscrashdumppathhelpers.hpp"
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
std::string Crash::getCrashDumpPath(const CrashSHM& crashShm)
|
||||||
|
{
|
||||||
|
return (boost::filesystem::path(crashShm.mStartup.mDumpDirectoryPath) / crashShm.mStartup.mCrashDumpFileName).string();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Crash::getFreezeDumpPath(const CrashSHM& crashShm)
|
||||||
|
{
|
||||||
|
return (boost::filesystem::path(crashShm.mStartup.mDumpDirectoryPath) / crashShm.mStartup.mFreezeDumpFileName).string();
|
||||||
|
}
|
13
components/crashcatcher/windowscrashdumppathhelpers.hpp
Normal file
13
components/crashcatcher/windowscrashdumppathhelpers.hpp
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef COMPONENTS_CRASH_WINDOWSCRASHDUMPPATHHELPERS_H
|
||||||
|
#include "windows_crashshm.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Crash
|
||||||
|
{
|
||||||
|
std::string getCrashDumpPath(const CrashSHM& crashShm);
|
||||||
|
|
||||||
|
std::string getFreezeDumpPath(const CrashSHM& crashShm);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -300,10 +300,8 @@ void setupLogging(const std::string& logDir, std::string_view appName)
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (Crash::CrashCatcher::instance())
|
if (Crash::CrashCatcher::instance())
|
||||||
{
|
{
|
||||||
const std::string crashDumpName = Misc::StringUtils::lowerCase(appName) + "-crash.dmp";
|
|
||||||
const std::string freezeDumpName = Misc::StringUtils::lowerCase(appName) + "-freeze.dmp";
|
|
||||||
boost::filesystem::path dumpDirectory(logDir);
|
boost::filesystem::path dumpDirectory(logDir);
|
||||||
Crash::CrashCatcher::instance()->updateDumpPaths((dumpDirectory / crashDumpName).make_preferred().string(), (dumpDirectory / freezeDumpName).make_preferred().string());
|
Crash::CrashCatcher::instance()->updateDumpPath(dumpDirectory.make_preferred().string());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -335,7 +333,7 @@ int wrapApplication(int (*innerApplication)(int argc, char *argv[]), int argc, c
|
||||||
dumpDirectory = userProfile;
|
dumpDirectory = userProfile;
|
||||||
}
|
}
|
||||||
CoTaskMemFree(userProfile);
|
CoTaskMemFree(userProfile);
|
||||||
Crash::CrashCatcher crashy(argc, argv, (dumpDirectory / crashDumpName).make_preferred().string(), (dumpDirectory / freezeDumpName).make_preferred().string());
|
Crash::CrashCatcher crashy(argc, argv, dumpDirectory.make_preferred().string(), crashDumpName, freezeDumpName);
|
||||||
#else
|
#else
|
||||||
const std::string crashLogName = Misc::StringUtils::lowerCase(appName) + "-crash.log";
|
const std::string crashLogName = Misc::StringUtils::lowerCase(appName) + "-crash.log";
|
||||||
// install the crash handler as soon as possible. note that the log path
|
// install the crash handler as soon as possible. note that the log path
|
||||||
|
|
Loading…
Reference in a new issue