193 lines
6.0 KiB
C++
193 lines
6.0 KiB
C++
#include "MetaCoreEditor/MetaCoreEditorApp.h"
|
|
|
|
#include <csignal>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <exception>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <new>
|
|
#include <vector>
|
|
|
|
#if defined(_WIN32)
|
|
#include <crtdbg.h>
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#include <windows.h>
|
|
#else
|
|
#include <limits.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
namespace {
|
|
|
|
std::filesystem::path MetaCoreGetExecutableDirectory() {
|
|
#if defined(_WIN32)
|
|
std::vector<wchar_t> buffer(MAX_PATH, L'\0');
|
|
while (true) {
|
|
const DWORD copied = GetModuleFileNameW(nullptr, buffer.data(), static_cast<DWORD>(buffer.size()));
|
|
if (copied == 0) {
|
|
return {};
|
|
}
|
|
|
|
if (copied < buffer.size() - 1) {
|
|
return std::filesystem::path(std::wstring(buffer.data(), copied)).parent_path();
|
|
}
|
|
|
|
buffer.resize(buffer.size() * 2, L'\0');
|
|
}
|
|
#else
|
|
std::vector<char> buffer(PATH_MAX, '\0');
|
|
while (true) {
|
|
const ssize_t copied = readlink("/proc/self/exe", buffer.data(), buffer.size());
|
|
if (copied < 0) {
|
|
return {};
|
|
}
|
|
|
|
if (static_cast<std::size_t>(copied) < buffer.size()) {
|
|
return std::filesystem::path(std::string(buffer.data(), static_cast<std::size_t>(copied))).parent_path();
|
|
}
|
|
|
|
buffer.resize(buffer.size() * 2, '\0');
|
|
}
|
|
#endif
|
|
}
|
|
|
|
std::filesystem::path MetaCoreGetCrashLogPath() {
|
|
const std::filesystem::path executableDirectory = MetaCoreGetExecutableDirectory();
|
|
if (!executableDirectory.empty()) {
|
|
return executableDirectory / "editor.crash.log";
|
|
}
|
|
return "editor.crash.log";
|
|
}
|
|
|
|
void MetaCoreResetCrashLog() {
|
|
std::ofstream stream(MetaCoreGetCrashLogPath(), std::ios::trunc);
|
|
}
|
|
|
|
void MetaCoreWriteCrashLog(const std::string& message) {
|
|
std::ofstream stream(MetaCoreGetCrashLogPath(), std::ios::app);
|
|
if (!stream.is_open()) {
|
|
return;
|
|
}
|
|
stream << message << '\n';
|
|
}
|
|
|
|
void MetaCoreWriteCrashLogRaw(const char* message) {
|
|
if (message == nullptr) {
|
|
return;
|
|
}
|
|
FILE* file = nullptr;
|
|
const std::filesystem::path crashLogPath = MetaCoreGetCrashLogPath();
|
|
#if defined(_WIN32)
|
|
if (fopen_s(&file, crashLogPath.string().c_str(), "a") == 0 && file != nullptr) {
|
|
#else
|
|
file = std::fopen(crashLogPath.string().c_str(), "a");
|
|
if (file != nullptr) {
|
|
#endif
|
|
std::fputs(message, file);
|
|
std::fputs("\n", file);
|
|
std::fclose(file);
|
|
}
|
|
}
|
|
|
|
#if defined(_WIN32)
|
|
void MetaCoreInvalidParameterHandler(
|
|
const wchar_t* expression,
|
|
const wchar_t* functionName,
|
|
const wchar_t* fileName,
|
|
unsigned int line,
|
|
uintptr_t reserved
|
|
) {
|
|
(void)reserved;
|
|
MetaCoreWriteCrashLog("metacore.app: invalid parameter triggered");
|
|
if (expression != nullptr) {
|
|
MetaCoreWriteCrashLog("metacore.app: invalid parameter expression=<non-null>");
|
|
}
|
|
if (functionName != nullptr) {
|
|
MetaCoreWriteCrashLog("metacore.app: invalid parameter function=<non-null>");
|
|
}
|
|
if (fileName != nullptr) {
|
|
MetaCoreWriteCrashLog("metacore.app: invalid parameter file=<non-null>");
|
|
}
|
|
MetaCoreWriteCrashLog("metacore.app: invalid parameter line=" + std::to_string(line));
|
|
}
|
|
|
|
void MetaCorePureCallHandler() {
|
|
MetaCoreWriteCrashLog("metacore.app: purecall handler triggered");
|
|
}
|
|
#endif
|
|
|
|
void MetaCoreSignalHandler(int signalValue) {
|
|
MetaCoreWriteCrashLog("metacore.app: signal=" + std::to_string(signalValue));
|
|
}
|
|
|
|
void MetaCoreTerminateHandler() {
|
|
MetaCoreWriteCrashLog("metacore.app: std::terminate triggered");
|
|
if (std::exception_ptr exceptionPtr = std::current_exception(); exceptionPtr != nullptr) {
|
|
try {
|
|
std::rethrow_exception(exceptionPtr);
|
|
} catch (const std::exception& exceptionObject) {
|
|
MetaCoreWriteCrashLog(std::string("metacore.app: exception=") + exceptionObject.what());
|
|
} catch (...) {
|
|
MetaCoreWriteCrashLog("metacore.app: exception=<non-std exception>");
|
|
}
|
|
} else {
|
|
MetaCoreWriteCrashLog("metacore.app: exception=<none>");
|
|
}
|
|
std::_Exit(3);
|
|
}
|
|
|
|
void MetaCoreInstallDebugCrashHooks() {
|
|
#if defined(_WIN32) && defined(_DEBUG)
|
|
_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
|
|
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
|
|
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
|
|
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
|
|
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
|
|
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
|
|
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
|
|
|
|
_set_invalid_parameter_handler(&MetaCoreInvalidParameterHandler);
|
|
_set_purecall_handler(&MetaCorePureCallHandler);
|
|
std::set_terminate(&MetaCoreTerminateHandler);
|
|
std::signal(SIGABRT, &MetaCoreSignalHandler);
|
|
MetaCoreWriteCrashLog("metacore.app: debug crash hooks installed");
|
|
#endif
|
|
}
|
|
|
|
} // namespace
|
|
int main(int argc, char* argv[]) {
|
|
if (argc > 0) {
|
|
const std::filesystem::path executableDirectory = MetaCoreGetExecutableDirectory();
|
|
if (!executableDirectory.empty()) {
|
|
std::filesystem::current_path(executableDirectory);
|
|
}
|
|
}
|
|
|
|
MetaCoreResetCrashLog();
|
|
MetaCoreInstallDebugCrashHooks();
|
|
MetaCoreWriteCrashLogRaw("metacore.app: hooks installed");
|
|
MetaCoreWriteCrashLogRaw("metacore.app: set current_path done");
|
|
|
|
MetaCoreWriteCrashLogRaw("metacore.app: construct app begin");
|
|
MetaCore::MetaCoreEditorApp editorApp;
|
|
MetaCoreWriteCrashLogRaw("metacore.app: construct app done");
|
|
MetaCoreWriteCrashLogRaw("metacore.app: initialize begin");
|
|
if (!editorApp.Initialize(argc, argv)) {
|
|
MetaCoreWriteCrashLogRaw("metacore.app: initialize failed");
|
|
std::cerr << "MetaCoreEditorApp initialize failed\n";
|
|
return 1;
|
|
}
|
|
MetaCoreWriteCrashLogRaw("metacore.app: initialize done");
|
|
|
|
MetaCoreWriteCrashLogRaw("metacore.app: run begin");
|
|
const int exitCode = editorApp.Run();
|
|
MetaCoreWriteCrashLogRaw("metacore.app: run done");
|
|
editorApp.Shutdown();
|
|
MetaCoreWriteCrashLogRaw("metacore.app: shutdown done");
|
|
return exitCode;
|
|
}
|