Sfoglia il codice sorgente

mini_dump: Cleanup and add comments

Removes some unnecessary code.

wip
lat9nq 4 anni fa
parent
commit
3dbaafe1f3
3 ha cambiato i file con 87 aggiunte e 43 eliminazioni
  1. 1 0
      src/yuzu/main.cpp
  2. 85 43
      src/yuzu/mini_dump.cpp
  3. 1 0
      src/yuzu/mini_dump.h

+ 1 - 0
src/yuzu/main.cpp

@@ -4097,6 +4097,7 @@ int main(int argc, char* argv[]) {
 #ifdef YUZU_DBGHELP
     PROCESS_INFORMATION pi;
     if (!is_child && Settings::values.create_crash_dumps.GetValue() && SpawnDebuggee(argv[0], pi)) {
+        // Delete the config object so that it doesn't save when the program exits
         config.reset(nullptr);
         DebugDebuggee(pi);
         return 0;

+ 85 - 43
src/yuzu/mini_dump.cpp

@@ -1,8 +1,8 @@
 #include <cstdio>
+#include <cstring>
 #include <ctime>
 #include <filesystem>
 #include <windows.h>
-#include "common/logging/log.h"
 #include "yuzu/mini_dump.h"
 #include "yuzu/startup_checks.h"
 
@@ -11,8 +11,6 @@
 
 void CreateMiniDump(HANDLE process_handle, DWORD process_id, MINIDUMP_EXCEPTION_INFORMATION* info,
                     EXCEPTION_POINTERS* pep) {
-    LOG_INFO(Core, "called");
-
     char file_name[255];
     const std::time_t the_time = std::time(nullptr);
     std::strftime(file_name, 255, "yuzu-crash-%Y%m%d%H%M%S.dmp", std::localtime(&the_time));
@@ -29,16 +27,50 @@ void CreateMiniDump(HANDLE process_handle, DWORD process_id, MINIDUMP_EXCEPTION_
                                                          dump_type, (pep != 0) ? info : 0, 0, 0);
 
         if (!write_dump_status) {
-            LOG_ERROR(Core, "MiniDumpWriteDump failed. Error: {}", GetLastError());
+            std::fprintf(stderr, "MiniDumpWriteDump failed. Error: %d\n", GetLastError());
         } else {
-            LOG_INFO(Core, "Minidump created.");
+            std::fprintf(stderr, "MiniDump created: %s\n", file_name);
         }
 
         // Close the file
         CloseHandle(file_handle);
 
     } else {
-        LOG_ERROR(Core, "CreateFile failed. Error: {}", GetLastError());
+        std::fprintf(stderr, "CreateFile failed. Error: %d\n", GetLastError());
+    }
+}
+
+void DumpFromDebugEvent(DEBUG_EVENT& deb_ev, PROCESS_INFORMATION& pi) {
+    EXCEPTION_RECORD& record = deb_ev.u.Exception.ExceptionRecord;
+
+    HANDLE thread_handle = OpenThread(THREAD_GET_CONTEXT, false, deb_ev.dwThreadId);
+    if (thread_handle == nullptr) {
+        std::fprintf(stderr, "OpenThread failed (%d)\n", GetLastError());
+    }
+
+    // Get child process context
+    CONTEXT context;
+    std::memset(&context, 0, sizeof(context));
+    context.ContextFlags = CONTEXT_ALL;
+    if (!GetThreadContext(thread_handle, &context)) {
+        std::fprintf(stderr, "GetThreadContext failed (%d)\n", GetLastError());
+        return;
+    }
+
+    // Create exception pointers for minidump
+    EXCEPTION_POINTERS ep;
+    ep.ExceptionRecord = &record;
+    ep.ContextRecord = &context;
+
+    MINIDUMP_EXCEPTION_INFORMATION info;
+    info.ThreadId = deb_ev.dwThreadId;
+    info.ExceptionPointers = &ep;
+    info.ClientPointers = false;
+
+    CreateMiniDump(pi.hProcess, pi.dwProcessId, &info, &ep);
+
+    if (CloseHandle(thread_handle) == 0) {
+        std::fprintf(stderr, "error: CloseHandle(thread_handle) failed (%d)\n", GetLastError());
     }
 }
 
@@ -68,6 +100,8 @@ bool SpawnDebuggee(const char* arg0, PROCESS_INFORMATION& pi) {
 
 void DebugDebuggee(PROCESS_INFORMATION& pi) {
     DEBUG_EVENT deb_ev;
+    const std::time_t start_time = std::time(nullptr);
+    //~ bool seen_nonzero_thread_exit = false;
 
     while (deb_ev.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT) {
         const bool wait_success = WaitForDebugEvent(&deb_ev, INFINITE);
@@ -87,49 +121,57 @@ void DebugDebuggee(PROCESS_INFORMATION& pi) {
         case UNLOAD_DLL_DEBUG_EVENT:
             ContinueDebugEvent(deb_ev.dwProcessId, deb_ev.dwThreadId, DBG_CONTINUE);
             break;
-        case EXCEPTION_DEBUG_EVENT:
+            //~ case EXIT_THREAD_DEBUG_EVENT: {
+            //~ const DWORD& exit_code = deb_ev.u.ExitThread.dwExitCode;
+
+            //~ // Generate a crash dump on the first abnormal thread exit.
+            //~ // We don't want to generate on every abnormal thread exit since ALL the other
+            // threads ~ // in the application will follow by exiting with the same code. ~ if
+            //(!seen_nonzero_thread_exit && exit_code != 0) { ~ seen_nonzero_thread_exit = true; ~
+            // std::fprintf(stderr, ~ "Creating MiniDump on first non-zero thread exit: code
+            // 0x%08x\n", ~ exit_code);
+            //~ DumpFromDebugEvent(deb_ev, pi);
+            //~ }
+            //~ ContinueDebugEvent(deb_ev.dwProcessId, deb_ev.dwThreadId, DBG_CONTINUE);
+            //~ break;
+        //~ }
+        case EXCEPTION_DEBUG_EVENT: {
             EXCEPTION_RECORD& record = deb_ev.u.Exception.ExceptionRecord;
-
-            std::fprintf(stderr, "ExceptionCode: 0x%08x %s\n", record.ExceptionCode,
-                         ExceptionName(record.ExceptionCode));
-            if (!deb_ev.u.Exception.dwFirstChance) {
-                HANDLE thread_handle = OpenThread(THREAD_ALL_ACCESS, false, deb_ev.dwThreadId);
-                if (thread_handle == nullptr) {
-                    std::fprintf(stderr, "OpenThread failed (%d)\n", GetLastError());
-                }
-                if (SuspendThread(thread_handle) == (DWORD)-1) {
-                    std::fprintf(stderr, "SuspendThread failed (%d)\n", GetLastError());
-                }
-
-                CONTEXT context;
-                std::memset(&context, 0, sizeof(context));
-                context.ContextFlags = CONTEXT_ALL;
-                if (!GetThreadContext(thread_handle, &context)) {
-                    std::fprintf(stderr, "GetThreadContext failed (%d)\n", GetLastError());
-                    break;
-                }
-
-                EXCEPTION_POINTERS ep;
-                ep.ExceptionRecord = &record;
-                ep.ContextRecord = &context;
-
-                MINIDUMP_EXCEPTION_INFORMATION info;
-                info.ThreadId = deb_ev.dwThreadId;
-                info.ExceptionPointers = &ep;
-                info.ClientPointers = false;
-
-                CreateMiniDump(pi.hProcess, pi.dwProcessId, &info, &ep);
-
-                std::fprintf(stderr, "previous thread suspend count: %d\n",
-                             ResumeThread(thread_handle));
-                if (CloseHandle(thread_handle) == 0) {
-                    std::fprintf(stderr, "error: CloseHandle(thread_handle) failed (%d)\n",
-                                 GetLastError());
+            const std::time_t now = std::time(nullptr);
+            const std::time_t delta = now - start_time;
+
+            if (ExceptionName(record.ExceptionCode) == nullptr) {
+                int record_count = 0;
+                EXCEPTION_RECORD* next_record = &deb_ev.u.Exception.ExceptionRecord;
+                while (next_record != nullptr) {
+                    std::fprintf(stderr,
+                                 "[%d] code(%d): 0x%08x\n\tflags: %08x %s\n\taddress: "
+                                 "0x%08x\n\tparameters: %d\n",
+                                 delta, record_count, next_record->ExceptionCode,
+                                 next_record->ExceptionFlags,
+                                 next_record->ExceptionFlags == EXCEPTION_NONCONTINUABLE
+                                     ? "noncontinuable"
+                                     : "",
+                                 next_record->ExceptionAddress, next_record->NumberParameters);
+                    for (int i = 0; i < static_cast<int>(next_record->NumberParameters); i++) {
+                        std::fprintf(stderr, "\t\t%0d: 0x%08x\n", i,
+                                     next_record->ExceptionInformation[i]);
+                    }
+
+                    record_count++;
+                    next_record = next_record->ExceptionRecord;
                 }
             }
+            // We want to generate a crash dump if we are seeing the same exception again.
+            if (!deb_ev.u.Exception.dwFirstChance) {
+                std::fprintf(stderr, "Creating MiniDump on ExceptionCode: 0x%08x %s\n",
+                             record.ExceptionCode, ExceptionName(record.ExceptionCode));
+                DumpFromDebugEvent(deb_ev, pi);
+            }
             ContinueDebugEvent(deb_ev.dwProcessId, deb_ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
             break;
         }
+        }
     }
 }
 

+ 1 - 0
src/yuzu/mini_dump.h

@@ -7,6 +7,7 @@
 void CreateMiniDump(HANDLE process_handle, DWORD process_id, MINIDUMP_EXCEPTION_INFORMATION* info,
                     EXCEPTION_POINTERS* pep);
 
+void DumpFromDebugEvent(DEBUG_EVENT& deb_ev, PROCESS_INFORMATION& pi);
 bool SpawnDebuggee(const char* arg0, PROCESS_INFORMATION& pi);
 void DebugDebuggee(PROCESS_INFORMATION& pi);
 const char* ExceptionName(DWORD exception);