Debugging.cpp (3201B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "Public/winget/Debugging.h" 5 #include "Public/AppInstallerRuntime.h" 6 #include "Public/AppInstallerDateTime.h" 7 8 namespace AppInstaller::Debugging 9 { 10 namespace 11 { 12 constexpr std::string_view c_minidumpPrefix = "Minidump"; 13 constexpr std::string_view c_minidumpExtension = ".mdmp"; 14 15 struct SelfInitiatedMinidumpHelper 16 { 17 SelfInitiatedMinidumpHelper() : m_keepFile(false) 18 { 19 m_filePath = Runtime::GetPathTo(Runtime::PathName::DefaultLogLocation); 20 m_filePath /= c_minidumpPrefix.data() + ('-' + Utility::GetCurrentTimeForFilename() + c_minidumpExtension.data()); 21 22 m_file.reset(CreateFile(m_filePath.wstring().c_str(), GENERIC_READ | GENERIC_WRITE, 23 FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr)); 24 THROW_LAST_ERROR_IF(!m_file); 25 26 SetUnhandledExceptionFilter(UnhandledExceptionCallback); 27 } 28 29 ~SelfInitiatedMinidumpHelper() 30 { 31 if (!m_keepFile) 32 { 33 m_file.reset(); 34 DeleteFile(m_filePath.wstring().c_str()); 35 } 36 } 37 38 static SelfInitiatedMinidumpHelper& Instance() 39 { 40 static SelfInitiatedMinidumpHelper instance; 41 return instance; 42 } 43 44 static LONG WINAPI UnhandledExceptionCallback(EXCEPTION_POINTERS* ExceptionInfo) 45 { 46 MINIDUMP_EXCEPTION_INFORMATION exceptionInformation{}; 47 // The unhandled exception filter is executed in the context of the failing thread. 48 exceptionInformation.ThreadId = GetCurrentThreadId(); 49 exceptionInformation.ExceptionPointers = ExceptionInfo; 50 exceptionInformation.ClientPointers = FALSE; 51 52 std::thread([&]() { 53 MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), Instance().m_file.get(), MiniDumpNormal, &exceptionInformation, nullptr, nullptr); 54 Instance().m_keepFile = true; 55 }).join(); 56 57 return EXCEPTION_CONTINUE_SEARCH; 58 } 59 60 void WriteMinidump() 61 { 62 std::thread([&]() { 63 MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), Instance().m_file.get(), MiniDumpNormal, nullptr, nullptr, nullptr); 64 Instance().m_keepFile = true; 65 }).join(); 66 } 67 68 private: 69 std::filesystem::path m_filePath; 70 wil::unique_handle m_file; 71 std::atomic_bool m_keepFile; 72 }; 73 } 74 75 void EnableSelfInitiatedMinidump() 76 { 77 // Force object creation and thus enabling of the crash detection. 78 SelfInitiatedMinidumpHelper::Instance(); 79 } 80 81 void WriteMinidump() 82 { 83 SelfInitiatedMinidumpHelper::Instance().WriteMinidump(); 84 } 85 }