Commit 8fa9b57f75186f641e920ac194e7c748a42d2a26

Ryan C. Gordon 2017-01-27T20:50:30

windows: first shot at naming threads with SetThreadDescription(). This is a bleeding edge API, added to Windows 10 Anniversary Edition (build 1607, specifically). https://msdn.microsoft.com/en-us/library/windows/desktop/mt774976(v=vs.85).aspx Nothing supports this yet, including WinDbg, Visual Studio, minidumps, etc, so we still need to also use the RaiseException hack. But presumably tools will use this API as a more robust and universal way to get thread names sooner or later, so we'll start broadcasting to it now.

diff --git a/src/thread/windows/SDL_systhread.c b/src/thread/windows/SDL_systhread.c
index 1d159db..aa73354 100644
--- a/src/thread/windows/SDL_systhread.c
+++ b/src/thread/windows/SDL_systhread.c
@@ -164,26 +164,53 @@ typedef struct tagTHREADNAME_INFO
 } THREADNAME_INFO;
 #pragma pack(pop)
 
+
+typedef HRESULT (WINAPI *pfnSetThreadDescription)(HANDLE, PCWSTR);
+
 void
 SDL_SYS_SetupThread(const char *name)
 {
-    if ((name != NULL) && IsDebuggerPresent()) {
-        THREADNAME_INFO inf;
+    if (name != NULL) {
+        static HMODULE kernel32 = 0;
+        static pfnSetThreadDescription pSetThreadDescription = NULL;
+
+        if (!kernel32) {
+            kernel32 = LoadLibrary(L"kernel32.dll");
+            if (kernel32) {
+                pSetThreadDescription = (pfnSetThreadDescription) GetProcAddress(kernel32, "SetThreadDescription");
+            }
+        }
 
-        /* C# and friends will try to catch this Exception, let's avoid it. */
-        if (SDL_GetHintBoolean(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, SDL_FALSE)) {
-            return;
+        if (pSetThreadDescription != NULL) {
+            WCHAR *strw = WIN_UTF8ToString(name);
+            if (strw) {
+                pSetThreadDescription(GetCurrentThread(), strw);
+                SDL_free(strw);
+            }
         }
 
-        /* This magic tells the debugger to name a thread if it's listening. */
-        SDL_zero(inf);
-        inf.dwType = 0x1000;
-        inf.szName = name;
-        inf.dwThreadID = (DWORD) -1;
-        inf.dwFlags = 0;
+        /* Presumably some version of Visual Studio will understand SetThreadDescription(),
+           but we still need to deal with older OSes and debuggers. Set it with the arcane
+           exception magic, too. */
 
-        /* The debugger catches this, renames the thread, continues on. */
-        RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR*) &inf);
+        if (IsDebuggerPresent()) {
+            THREADNAME_INFO inf;
+
+            /* C# and friends will try to catch this Exception, let's avoid it. */
+            if (SDL_GetHintBoolean(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, SDL_FALSE)) {
+                return;
+            }
+
+            /* This magic tells the debugger to name a thread if it's listening. */
+            SDL_zero(inf);
+            inf.dwType = 0x1000;
+            inf.szName = name;
+            inf.dwThreadID = (DWORD) -1;
+            inf.dwFlags = 0;
+
+            /* The debugger catches this, renames the thread, continues on. */
+            RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR*) &inf);
+        }
     }
 }