| |
| |
|
|
| #include <algorithm> |
| #include <ranges> |
|
|
| #if defined(_WIN32) |
| #include <client/windows/handler/exception_handler.h> |
| #elif defined(__linux__) |
| #include <client/linux/handler/exception_handler.h> |
| #else |
| #error Minidump creation not supported on this platform |
| #endif |
|
|
| #include "common/fs/fs_paths.h" |
| #include "common/fs/path_util.h" |
| #include "yuzu/breakpad.h" |
|
|
| namespace Breakpad { |
|
|
| static void PruneDumpDirectory(const std::filesystem::path& dump_path) { |
| |
| struct Entry { |
| std::filesystem::path path; |
| std::filesystem::file_time_type last_write_time; |
| }; |
| std::vector<Entry> existing_dumps; |
|
|
| |
| std::error_code ec; |
| std::filesystem::directory_iterator dir(dump_path, ec); |
| for (auto& entry : dir) { |
| if (entry.is_regular_file()) { |
| existing_dumps.push_back(Entry{ |
| .path = entry.path(), |
| .last_write_time = entry.last_write_time(ec), |
| }); |
| } |
| } |
|
|
| |
| std::ranges::stable_sort(existing_dumps, [](const auto& a, const auto& b) { |
| return a.last_write_time > b.last_write_time; |
| }); |
|
|
| |
| for (size_t i = 5; i < existing_dumps.size(); i++) { |
| std::filesystem::remove(existing_dumps[i].path, ec); |
| } |
| } |
|
|
| #if defined(__linux__) |
| [[noreturn]] bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, |
| bool succeeded) { |
| |
| |
| _exit(1); |
| } |
| #endif |
|
|
| void InstallCrashHandler() { |
| |
| const auto dump_path = GetYuzuPath(Common::FS::YuzuPath::CrashDumpsDir); |
| PruneDumpDirectory(dump_path); |
|
|
| #if defined(_WIN32) |
| |
| static google_breakpad::ExceptionHandler eh{dump_path, nullptr, nullptr, nullptr, |
| google_breakpad::ExceptionHandler::HANDLER_ALL}; |
| #elif defined(__linux__) |
| static google_breakpad::MinidumpDescriptor descriptor{dump_path}; |
| static google_breakpad::ExceptionHandler eh{descriptor, nullptr, DumpCallback, |
| nullptr, true, -1}; |
| #endif |
| } |
|
|
| } |
|
|