From b90c15eab49a054eead6e7846617c1024db1f599 Mon Sep 17 00:00:00 2001 From: shweet Date: Wed, 14 Jan 2026 19:25:12 -0500 Subject: [PATCH] bring back windows dumps --- src/loader.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/loader.cpp b/src/loader.cpp index 3198a95..4db094a 100644 --- a/src/loader.cpp +++ b/src/loader.cpp @@ -37,6 +37,77 @@ namespace anm2ed constexpr int SOCKET_ERROR_ADDRESS_IN_USE = EADDRINUSE; #endif +#ifdef _WIN32 + std::filesystem::path g_minidump_dir{}; + PVOID g_vectored_handler{}; + LONG g_dump_in_progress{}; + + void windows_minidump_write(EXCEPTION_POINTERS* exceptionPointers) + { + if (g_minidump_dir.empty()) return; + if (InterlockedExchange(&g_dump_in_progress, 1) != 0) return; + + SYSTEMTIME st{}; + GetLocalTime(&st); + + auto pid = GetCurrentProcessId(); + auto code = exceptionPointers && exceptionPointers->ExceptionRecord + ? exceptionPointers->ExceptionRecord->ExceptionCode + : 0u; + + auto filename = std::format("anm2ed_{:04}{:02}{:02}_{:02}{:02}{:02}_pid{:08x}_code{:08x}.dmp", st.wYear, st.wMonth, + st.wDay, st.wHour, st.wMinute, st.wSecond, pid, code); + auto dumpPath = g_minidump_dir / path::from_utf8(filename); + + auto dumpPathW = dumpPath.wstring(); + HANDLE file = CreateFileW(dumpPathW.c_str(), GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, nullptr); + if (file == INVALID_HANDLE_VALUE) return; + + MINIDUMP_EXCEPTION_INFORMATION mei{}; + mei.ThreadId = GetCurrentThreadId(); + mei.ExceptionPointers = exceptionPointers; + mei.ClientPointers = FALSE; + + const MINIDUMP_TYPE dumpType = static_cast(MiniDumpNormal | MiniDumpWithIndirectlyReferencedMemory | + MiniDumpWithThreadInfo | MiniDumpWithUnloadedModules); + MiniDumpWriteDump(GetCurrentProcess(), pid, file, dumpType, exceptionPointers ? &mei : nullptr, nullptr, nullptr); + + FlushFileBuffers(file); + CloseHandle(file); + } + + LONG WINAPI windows_unhandled_exception_filter(EXCEPTION_POINTERS* exceptionPointers) + { + windows_minidump_write(exceptionPointers); + return EXCEPTION_EXECUTE_HANDLER; + } + + LONG CALLBACK windows_vectored_exception_handler(EXCEPTION_POINTERS* exceptionPointers) + { + windows_minidump_write(exceptionPointers); + return EXCEPTION_CONTINUE_SEARCH; + } + + void windows_minidumps_configure() + { + auto prefDir = sdl::preferences_directory_get(); + if (prefDir.empty()) return; + + std::error_code ec{}; + auto dumpDir = prefDir / "crash"; + std::filesystem::create_directories(dumpDir, ec); + if (ec) return; + + g_minidump_dir = dumpDir; + + if (!g_vectored_handler) g_vectored_handler = AddVectoredExceptionHandler(1, windows_vectored_exception_handler); + SetUnhandledExceptionFilter(windows_unhandled_exception_filter); + + logger.info(std::format("MiniDumpWriteDump enabled: {}", path::to_utf8(dumpDir))); + } +#endif + bool socket_paths_send(Socket& socket, const std::vector& paths) { uint32_t count = htonl(static_cast(paths.size())); @@ -135,6 +206,10 @@ namespace anm2ed logger.info("Initialized SDL"); +#ifdef _WIN32 + windows_minidumps_configure(); +#endif + auto windowProperties = SDL_CreateProperties(); if (windowProperties == 0)