Selaa lähdekoodia

libobs: Include thread names in thread traces

Makes the crashlog a little nicer to read.
Henrik "Henke37" Andersson 5 vuotta sitten
vanhempi
sitoutus
f0ad7a92cd
1 muutettua tiedostoa jossa 44 lisäystä ja 2 poistoa
  1. 44 2
      libobs/obs-win-crash-handler.c

+ 44 - 2
libobs/obs-win-crash-handler.c

@@ -67,6 +67,8 @@ typedef HINSTANCE(WINAPI *SHELLEXECUTEA)(HWND hwnd, LPCTSTR operation,
 					 LPCTSTR file, LPCTSTR parameters,
 					 LPCTSTR directory, INT show_flags);
 
+typedef HRESULT(WINAPI *GETTHREADDESCRIPTION)(HANDLE thread, PWSTR *desc);
+
 struct stack_trace {
 	CONTEXT context;
 	DWORD64 instruction_ptr;
@@ -391,6 +393,40 @@ static inline bool walk_stack(struct exception_handler_data *data,
 	"Arg1     Arg2     Arg3     Address\r\n"
 #endif
 
+static inline char *get_thread_name(HANDLE thread)
+{
+	static GETTHREADDESCRIPTION get_thread_desc = NULL;
+	static bool failed = false;
+
+	if (!get_thread_desc) {
+		if (failed) {
+			return NULL;
+		}
+
+		HMODULE k32 = LoadLibraryW(L"kernel32.dll");
+		get_thread_desc = (GETTHREADDESCRIPTION)GetProcAddress(
+			k32, "GetThreadDescription");
+		if (!get_thread_desc) {
+			failed = true;
+			return NULL;
+		}
+	}
+
+	wchar_t *w_name;
+	HRESULT hr = get_thread_desc(thread, &w_name);
+	if (FAILED(hr) || !w_name) {
+		return NULL;
+	}
+
+	struct dstr name = {0};
+	dstr_from_wcs(&name, w_name);
+	if (name.len)
+		dstr_insert_ch(&name, 0, ' ');
+	LocalFree(w_name);
+
+	return name.array;
+}
+
 static inline void write_thread_trace(struct exception_handler_data *data,
 				      THREADENTRY32 *entry, bool first_thread)
 {
@@ -398,6 +434,7 @@ static inline void write_thread_trace(struct exception_handler_data *data,
 	struct stack_trace trace = {0};
 	struct stack_trace *ptrace;
 	HANDLE thread;
+	char *thread_name;
 
 	if (first_thread != crash_thread)
 		return;
@@ -413,8 +450,13 @@ static inline void write_thread_trace(struct exception_handler_data *data,
 	GetThreadContext(thread, &trace.context);
 	init_instruction_data(&trace);
 
-	dstr_catf(&data->str, "\r\nThread %lX%s\r\n" TRACE_TOP,
-		  entry->th32ThreadID, crash_thread ? " (Crashed)" : "");
+	thread_name = get_thread_name(thread);
+
+	dstr_catf(&data->str, "\r\nThread %lX:%s%s\r\n" TRACE_TOP,
+		  entry->th32ThreadID, thread_name ? thread_name : "",
+		  crash_thread ? " (Crashed)" : "");
+
+	bfree(thread_name);
 
 	ptrace = crash_thread ? &data->main_trace : &trace;