This is the mail archive of the cygwin-patches mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 2/2] Send thread names to debugger


GDB with the patch from [1] can report and use these names.

Add utility function SetThreadName(), which sends a thread name to the
debugger.

Wire this up to set the default thread name for main thread and newly
created pthreads.

Wire this up in pthread_setname_np() for user thread names.

Wire this up in cygthread::create() for helper thread names.  Also wire it
up for helper threads which are created directly with CreateThread.

TODO: Make SetThreadName() available to libgmon.a so the profiling thread
created by that can be named as well.

Note that there can still be anonymous threads, created by the kernel or
injected DLLs.

[1] https://sourceware.org/ml/gdb-patches/2016-07/msg00307.html

Signed-off-by: Jon Turney <jon.turney@dronecode.org.uk>
---
 winsup/cygwin/cygthread.cc  |  2 ++
 winsup/cygwin/dcrt0.cc      |  1 +
 winsup/cygwin/exceptions.cc |  2 +-
 winsup/cygwin/miscfuncs.cc  | 28 ++++++++++++++++++++++++++++
 winsup/cygwin/miscfuncs.h   |  2 ++
 winsup/cygwin/net.cc        |  2 ++
 winsup/cygwin/profil.c      |  2 ++
 winsup/cygwin/thread.cc     |  5 +++++
 8 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc
index b9d706b..2f7f2a1 100644
--- a/winsup/cygwin/cygthread.cc
+++ b/winsup/cygwin/cygthread.cc
@@ -213,6 +213,8 @@ cygthread::create ()
 			    this, 0, &id);
       if (!htobe)
 	api_fatal ("CreateThread failed for %s - %p<%y>, %E", __name, h, id);
+      else
+	SetThreadName(GetThreadId(htobe), __name);
       thread_printf ("created name '%s', thread %p, id %y", __name, h, id);
 #ifdef DEBUGGING
       terminated = false;
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 2328411..de581c1 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -964,6 +964,7 @@ dll_crt0_1 (void *)
       if (cp > __progname && ascii_strcasematch (cp, ".exe"))
 	*cp = '\0';
     }
+  SetThreadName(GetCurrentThreadId(), program_invocation_short_name);
 
   (void) xdr_set_vprintf (&cygxdr_vwarnx);
   cygwin_finished_initializing = true;
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index d65f56e..1d028a7 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -1288,7 +1288,7 @@ DWORD WINAPI
 dumpstack_overflow_wrapper (PVOID arg)
 {
   cygwin_exception *exc = (cygwin_exception *) arg;
-
+  SetThreadName(GetCurrentThreadId(), "dumpstack_overflow");
   exc->dumpstack ();
   return 0;
 }
diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc
index d0e4bf7..353633b 100644
--- a/winsup/cygwin/miscfuncs.cc
+++ b/winsup/cygwin/miscfuncs.cc
@@ -1110,3 +1110,31 @@ wmemcpy:								\n\
 	.seh_endproc							\n\
 ");
 #endif
+
+//
+// Signal the thread name to any attached debugger
+//
+// (See "How to: Set a Thread Name in Native Code"
+// https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx)
+//
+
+#define MS_VC_EXCEPTION 0x406D1388
+
+void
+SetThreadName(DWORD dwThreadID, const char* threadName)
+{
+  if (!IsDebuggerPresent ())
+    return;
+
+  ULONG_PTR info[] =
+    {
+      0x1000,                /* type, must be 0x1000 */
+      (ULONG_PTR)threadName, /* pointer to threadname */
+      dwThreadID,            /* thread ID (+ flags on x86_64) */
+#ifdef __X86__
+      0,                     /* flags, must be zero */
+#endif
+    };
+
+  RaiseException (MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR *) &info);
+}
diff --git a/winsup/cygwin/miscfuncs.h b/winsup/cygwin/miscfuncs.h
index a885dcf..5390dd1 100644
--- a/winsup/cygwin/miscfuncs.h
+++ b/winsup/cygwin/miscfuncs.h
@@ -85,4 +85,6 @@ extern "C" HANDLE WINAPI CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func,
 					     DWORD creation_flags,
 					     LPDWORD thread_id);
 
+void SetThreadName(DWORD dwThreadID, const char* threadName);
+
 #endif /*_MISCFUNCS_H*/
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index 52b3d98..94ae604 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -1776,6 +1776,8 @@ call_gaa (LPVOID param)
   gaa_wa *p = (gaa_wa *) param;
   PIP_ADAPTER_ADDRESSES pa0 = NULL;
 
+  SetThreadName(GetCurrentThreadId(), "call_gaa");
+
   if (!p->pa_ret)
     return GetAdaptersAddresses (p->family, GAA_FLAG_INCLUDE_PREFIX
 					    | GAA_FLAG_INCLUDE_ALL_INTERFACES,
diff --git a/winsup/cygwin/profil.c b/winsup/cygwin/profil.c
index be59b49..4b2e873 100644
--- a/winsup/cygwin/profil.c
+++ b/winsup/cygwin/profil.c
@@ -91,6 +91,8 @@ static void CALLBACK
 profthr_func (LPVOID arg)
 {
   struct profinfo *p = (struct profinfo *) arg;
+  // XXX: can't use SetThreadName() here as it's part of the cygwin DLL
+  // SetThreadName(GetCurrentThreadId(), "prof");
 
   for (;;)
     {
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index e41e0c1..7f60db7 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -1985,6 +1985,9 @@ pthread::thread_init_wrapper (void *arg)
   _my_tls.sigmask = thread->parent_sigmask;
   thread->set_tls_self_pointer ();
 
+  // Give thread default name
+  SetThreadName(GetCurrentThreadId(), program_invocation_short_name);
+
   thread->mutex.lock ();
 
   // if thread is detached force cleanup on exit
@@ -2622,6 +2625,8 @@ pthread_setname_np (pthread_t thread, const char *name)
   oldname = thread->attr.name;
   thread->attr.name = cp;
 
+  SetThreadName(GetThreadId(thread->win32_obj_id), thread->attr.name);
+
   if (oldname)
     free(oldname);
 
-- 
2.8.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]