Windows: let threads be named in the debugger.
authorRyan C. Gordon <icculus@icculus.org>
Sun, 21 Feb 2016 17:05:25 -0500
changeset 10087 96f7be2c885b
parent 10085 a8e53dc3c5a1
child 10088 33bee97dbcbb
Windows: let threads be named in the debugger. We now only raise the magic exception that names the thread when IsDebuggerPresent() returns true. In such a case, Visual Studio will catch the exception, set the thread name, and let the debugged process continue normally. If the debugger isn't running, we don't raise an exception at all. Setting the name is a debugger trick; if the debugger isn't running, the name won't be set if attached later in any case, so this doesn't lose functionality. This lets this code work without assembly code, on win32 and win64, and across various compilers. The only "gotcha" is that if you have something attached that looks like a debugger but doesn't respect this magic exception trick, the process will likely crash, but that's probably a deficiency of the attached program. Fixes Bugzilla #2089.
src/thread/windows/SDL_systhread.c
--- a/src/thread/windows/SDL_systhread.c	Sun Feb 21 13:07:14 2016 -0500
+++ b/src/thread/windows/SDL_systhread.c	Sun Feb 21 17:05:25 2016 -0500
@@ -145,9 +145,6 @@
     return 0;
 }
 
-#if 0  /* !!! FIXME: revisit this later. See https://bugzilla.libsdl.org/show_bug.cgi?id=2089 */
-#ifdef _MSC_VER
-#pragma warning(disable : 4733)
 #pragma pack(push,8)
 typedef struct tagTHREADNAME_INFO
 {
@@ -158,48 +155,20 @@
 } THREADNAME_INFO;
 #pragma pack(pop)
 
-static EXCEPTION_DISPOSITION
-ignore_exception(void *a, void *b, void *c, void *d)
-{
-    return ExceptionContinueExecution;
-}
-#endif
-#endif
-
 void
 SDL_SYS_SetupThread(const char *name)
 {
-    if (name != NULL) {
-        #if 0 /* !!! FIXME: revisit this later. See https://bugzilla.libsdl.org/show_bug.cgi?id=2089 */
-        #if (defined(_MSC_VER) && defined(_M_IX86))
-        /* This magic tells the debugger to name a thread if it's listening.
-            The inline asm sets up SEH (__try/__except) without C runtime
-            support. See Microsoft Systems Journal, January 1997:
-            http://www.microsoft.com/msj/0197/exception/exception.aspx */
-        INT_PTR handler = (INT_PTR) ignore_exception;
+    if ((name != NULL) && IsDebuggerPresent()) {
+        /* This magic tells the debugger to name a thread if it's listening. */
         THREADNAME_INFO inf;
-
+        SDL_zero(inf);
         inf.dwType = 0x1000;
         inf.szName = name;
         inf.dwThreadID = (DWORD) -1;
         inf.dwFlags = 0;
 
-        __asm {   /* set up SEH */
-            push handler
-            push fs:[0]
-            mov fs:[0],esp
-        }
-
-        /* The program itself should ignore this bogus exception. */
-        RaiseException(0x406D1388, 0, sizeof(inf)/sizeof(DWORD), (DWORD*)&inf);
-
-        __asm {  /* tear down SEH. */
-            mov eax,[esp]
-            mov fs:[0], eax
-            add esp, 8
-        }
-        #endif
-        #endif
+        /* The debugger catches this, renames the thread, continues on. */
+        RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR*) &inf);
     }
 }