Quantcast

[PATCH 0/2] Thread name support

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH 0/2] Thread name support

Jon TURNEY
Re-heat Yaakov's patch [1] for adding pthread_getname_np and pthread_setname_np
Use the native interface [2] for sending thread names to debugger
 
[1] https://cygwin.com/ml/cygwin-patches/2012-q1/msg00022.html
[2] https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx

Jon Turney (2):
  Add pthread_getname_np and pthread_setname_np
  Send thread names to debugger

 winsup/cygwin/common.din               |  2 ++
 winsup/cygwin/cygthread.cc             |  2 ++
 winsup/cygwin/dcrt0.cc                 |  1 +
 winsup/cygwin/exceptions.cc            |  2 +-
 winsup/cygwin/include/cygwin/version.h |  3 +-
 winsup/cygwin/include/pthread.h        |  2 ++
 winsup/cygwin/miscfuncs.cc             | 28 +++++++++++++++
 winsup/cygwin/miscfuncs.h              |  2 ++
 winsup/cygwin/net.cc                   |  2 ++
 winsup/cygwin/profil.c                 |  2 ++
 winsup/cygwin/release/2.6.0            |  4 +++
 winsup/cygwin/thread.cc                | 66 +++++++++++++++++++++++++++++++++-
 winsup/cygwin/thread.h                 |  1 +
 winsup/doc/new-features.xml            | 12 +++++++
 winsup/doc/posix.xml                   |  2 ++
 15 files changed, 128 insertions(+), 3 deletions(-)
 create mode 100644 winsup/cygwin/release/2.6.0

--
2.8.3

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH 1/2] Add pthread_getname_np and pthread_setname_np

Jon TURNEY
This patch adds pthread_getname_np and pthread_setname_np.

These were added to glibc in 2.12[1] and are also present in some form on
NetBSD and several UNIXes.

The code is based on NetBSD's implementation with changes to better match
Linux behaviour.

Implementation quirks:

* pthread_setname_np with a NULL pointer segfaults (as linux)

* pthread_setname_np accepts names longer than 16 characters (linux returns
ERANGE)

* pthread_getname_np with a NULL pointer returns EFAULT (as linux)

* pthread_getname_np with a buffer length of less than 16 returns ERANGE (as
linux)

* pthread_getname_np truncates the thread name to fit the buffer length.
This guarantees success even when the default thread name is longer than 16
characters, but means there is no way to discover the actual length of the
thread name. (Linux always truncates the thread name to 16 characters)

* Changing program_invocation_short_name changes the default thread name.

I'll leave it up to you to decide any of these matter.

This is implemented via class pthread_attr to make it easier to add
pthread_attr_[gs]etname_np (present in NetBSD and some UNIXes) should it
ever be added to Linux (or we decide we want it anyway).

[1] https://sourceware.org/git/?p=glibc.git;a=blob;f=NEWS;h=d55a844d4ec06d164cb786c6c9f403a9672a674d;hb=e28c88707ef0529593fccedf1a94c3fce3df0ef3

Signed-off-by: Jon Turney <[hidden email]>
---
 winsup/cygwin/common.din               |  2 ++
 winsup/cygwin/include/cygwin/version.h |  3 +-
 winsup/cygwin/include/pthread.h        |  2 ++
 winsup/cygwin/release/2.6.0            |  4 +++
 winsup/cygwin/thread.cc                | 61 +++++++++++++++++++++++++++++++++-
 winsup/cygwin/thread.h                 |  1 +
 winsup/doc/new-features.xml            | 12 +++++++
 winsup/doc/posix.xml                   |  2 ++
 8 files changed, 85 insertions(+), 2 deletions(-)
 create mode 100644 winsup/cygwin/release/2.6.0

diff --git a/winsup/cygwin/common.din b/winsup/cygwin/common.din
index d8df00e..1ebba2b 100644
--- a/winsup/cygwin/common.din
+++ b/winsup/cygwin/common.din
@@ -1014,6 +1014,7 @@ pthread_exit SIGFE
 pthread_getattr_np SIGFE
 pthread_getconcurrency SIGFE
 pthread_getcpuclockid SIGFE
+pthread_getname_np SIGFE
 pthread_getschedparam SIGFE
 pthread_getsequence_np SIGFE
 pthread_getspecific SIGFE
@@ -1054,6 +1055,7 @@ pthread_self SIGFE
 pthread_setcancelstate SIGFE
 pthread_setcanceltype SIGFE
 pthread_setconcurrency SIGFE
+pthread_setname_np SIGFE
 pthread_setschedparam SIGFE
 pthread_setschedprio SIGFE
 pthread_setspecific SIGFE
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index 1f5bf72..d403f0e 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -454,12 +454,13 @@ details. */
        nexttowardf, nexttowardl, pow10l, powl, remainderl, remquol, roundl,
        scalbl, scalblnl, scalbnl, sincosl, sinhl, sinl, tanhl, tanl,
        tgammal, truncl.
+  298: Export pthread_getname_np, pthread_setname_np.
 
   Note that we forgot to bump the api for ualarm, strtoll, strtoull,
   sigaltstack, sethostname. */
 
 #define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 297
+#define CYGWIN_VERSION_API_MINOR 298
 
 /* There is also a compatibity version number associated with the shared memory
    regions.  It is incremented when incompatible changes are made to the shared
diff --git a/winsup/cygwin/include/pthread.h b/winsup/cygwin/include/pthread.h
index 609eac2..47ee6bd 100644
--- a/winsup/cygwin/include/pthread.h
+++ b/winsup/cygwin/include/pthread.h
@@ -222,6 +222,8 @@ void pthread_testcancel (void);
 
 #if __GNU_VISIBLE
 int pthread_getattr_np (pthread_t, pthread_attr_t *);
+int pthread_getname_np (pthread_t, char *, size_t) __attribute__((nonnull(2)));
+int pthread_setname_np (pthread_t, const char *) __attribute__((nonnull(2)));
 int pthread_sigqueue (pthread_t *, int, const union sigval);
 int pthread_yield (void);
 #endif
diff --git a/winsup/cygwin/release/2.6.0 b/winsup/cygwin/release/2.6.0
new file mode 100644
index 0000000..5f9f4db
--- /dev/null
+++ b/winsup/cygwin/release/2.6.0
@@ -0,0 +1,4 @@
+What's new:
+-----------
+
+- New API: pthread_getname_np, pthread_setname_np, scandirat.
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index d9271fc..e41e0c1 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -1099,7 +1099,7 @@ pthread::resume ()
 pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC),
 joinable (PTHREAD_CREATE_JOINABLE), contentionscope (PTHREAD_SCOPE_PROCESS),
 inheritsched (PTHREAD_INHERIT_SCHED), stackaddr (NULL), stacksize (0),
-guardsize (wincap.def_guard_page_size ())
+guardsize (wincap.def_guard_page_size ()), name (NULL)
 {
   schedparam.sched_priority = 0;
 }
@@ -2569,6 +2569,65 @@ pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
   return 0;
 }
 
+#define NAMELEN 16
+
+extern "C" int
+pthread_getname_np (pthread_t thread, char *buf, size_t buflen)
+{
+  char *name;
+
+  if (!pthread::is_good_object (&thread))
+    return ESRCH;
+
+  if (!thread->attr.name)
+    name = program_invocation_short_name;
+  else
+    name = thread->attr.name;
+
+  // Return ERANGE if the provided buffer is less than NAMELEN.  Truncate and
+  // zero-terminate the name to fit in buf.  This means we always return
+  // something if the buffer is NAMELEN or larger, but there is no way to tell
+  // if we have the whole name.
+  if (buflen < NAMELEN)
+    return ERANGE;
+
+  int ret = 0;
+  __try
+    {
+      strlcpy (buf, name, buflen);
+    }
+  __except (NO_ERROR)
+    {
+      ret = EFAULT;
+    }
+  __endtry
+
+  return ret;
+}
+
+#undef NAMELEN
+
+extern "C" int
+pthread_setname_np (pthread_t thread, const char *name)
+{
+  char *oldname, *cp;
+
+  if (!pthread::is_good_object (&thread))
+    return ESRCH;
+
+  cp = strdup(name);
+  if (!cp)
+    return ENOMEM;
+
+  oldname = thread->attr.name;
+  thread->attr.name = cp;
+
+  if (oldname)
+    free(oldname);
+
+  return 0;
+}
+
 /* provided for source level compatability.
    See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
 */
diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h
index 5d51913..48fb6fb 100644
--- a/winsup/cygwin/thread.h
+++ b/winsup/cygwin/thread.h
@@ -240,6 +240,7 @@ public:
   void *stackaddr;
   size_t stacksize;
   size_t guardsize;
+  char *name;
 
   pthread_attr ();
   ~pthread_attr ();
diff --git a/winsup/doc/new-features.xml b/winsup/doc/new-features.xml
index 9d428e2..c9b9bee 100644
--- a/winsup/doc/new-features.xml
+++ b/winsup/doc/new-features.xml
@@ -4,6 +4,18 @@
 
 <sect1 id="ov-new"><title>What's new and what changed in Cygwin</title>
 
+<sect2 id="ov-new2.6"><title>What's new and what changed in 2.6</title>
+
+<itemizedlist mark="bullet">
+
+<listitem><para>
+New API: pthread_getname_np, pthread_setname_np.
+</para></listitem>
+
+</itemizedlist>
+
+<sect2>
+
 <sect2 id="ov-new2.5"><title>What's new and what changed in 2.5</title>
 
 <itemizedlist mark="bullet">
diff --git a/winsup/doc/posix.xml b/winsup/doc/posix.xml
index 83fa768..d502e30 100644
--- a/winsup/doc/posix.xml
+++ b/winsup/doc/posix.xml
@@ -1291,6 +1291,8 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
     pow10l
     ppoll
     pthread_getattr_np
+    pthread_getname_np
+    pthread_setname_np
     pthread_sigqueue
     ptsname_r
     putwc_unlocked
--
2.8.3

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH 2/2] Send thread names to debugger

Jon TURNEY
In reply to this post by Jon TURNEY
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 <[hidden email]>
---
 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

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH 1/2] Add pthread_getname_np and pthread_setname_np

Corinna Vinschen-2
In reply to this post by Jon TURNEY
Hi Jon,

On Jul 28 12:43, Jon Turney wrote:

> This patch adds pthread_getname_np and pthread_setname_np.
>
> These were added to glibc in 2.12[1] and are also present in some form on
> NetBSD and several UNIXes.
>
> The code is based on NetBSD's implementation with changes to better match
> Linux behaviour.
>
> Implementation quirks:
>
> * pthread_setname_np with a NULL pointer segfaults (as linux)
>
> * pthread_setname_np accepts names longer than 16 characters (linux returns
> ERANGE)
Given the behaviour of pthread_getname_np we should do the same, I think.

> * pthread_getname_np with a NULL pointer returns EFAULT (as linux)
>
> * pthread_getname_np with a buffer length of less than 16 returns ERANGE (as
> linux)
>
> * pthread_getname_np truncates the thread name to fit the buffer length.
> This guarantees success even when the default thread name is longer than 16
> characters, but means there is no way to discover the actual length of the
> thread name. (Linux always truncates the thread name to 16 characters)
>
> * Changing program_invocation_short_name changes the default thread name.
>
> I'll leave it up to you to decide any of these matter.
>
> This is implemented via class pthread_attr to make it easier to add
> pthread_attr_[gs]etname_np (present in NetBSD and some UNIXes) should it
> ever be added to Linux (or we decide we want it anyway).
Good thinking.

> [1] https://sourceware.org/git/?p=glibc.git;a=blob;f=NEWS;h=d55a844d4ec06d164cb786c6c9f403a9672a674d;hb=e28c88707ef0529593fccedf1a94c3fce3df0ef3
>
> diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
> index 1f5bf72..d403f0e 100644
> --- a/winsup/cygwin/include/cygwin/version.h
> +++ b/winsup/cygwin/include/cygwin/version.h
> @@ -454,12 +454,13 @@ details. */
>         nexttowardf, nexttowardl, pow10l, powl, remainderl, remquol, roundl,
>         scalbl, scalblnl, scalbnl, sincosl, sinhl, sinl, tanhl, tanl,
>         tgammal, truncl.
> +  298: Export pthread_getname_np, pthread_setname_np.
Yuk!  This collides with my changes in topic/locales.  Oh well, nothing
we can do about it...

> --- a/winsup/cygwin/thread.cc
> +++ b/winsup/cygwin/thread.cc
> @@ -1099,7 +1099,7 @@ pthread::resume ()
>  pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC),
>  joinable (PTHREAD_CREATE_JOINABLE), contentionscope (PTHREAD_SCOPE_PROCESS),
>  inheritsched (PTHREAD_INHERIT_SCHED), stackaddr (NULL), stacksize (0),
> -guardsize (wincap.def_guard_page_size ())
> +guardsize (wincap.def_guard_page_size ()), name (NULL)
>  {
>    schedparam.sched_priority = 0;
>  }
> @@ -2569,6 +2569,65 @@ pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
>    return 0;
>  }
>  
> +#define NAMELEN 16
> +
> +extern "C" int
> +pthread_getname_np (pthread_t thread, char *buf, size_t buflen)
> +{
> +  char *name;
> +
> +  if (!pthread::is_good_object (&thread))
> +    return ESRCH;
> +
> +  if (!thread->attr.name)
> +    name = program_invocation_short_name;
> +  else
> +    name = thread->attr.name;
> +
> +  // Return ERANGE if the provided buffer is less than NAMELEN.  Truncate and
> +  // zero-terminate the name to fit in buf.  This means we always return
> +  // something if the buffer is NAMELEN or larger, but there is no way to tell
> +  // if we have the whole name.
Please use C-style /* */ bracketing for multiline comments.

> +  if (buflen < NAMELEN)
> +    return ERANGE;
> +
> +  int ret = 0;
> +  __try
> +    {
> +      strlcpy (buf, name, buflen);
> +    }
> +  __except (NO_ERROR)
> +    {
> +      ret = EFAULT;
> +    }
> +  __endtry
> +
> +  return ret;
> +}
> +
> +#undef NAMELEN
> +
> +extern "C" int
> +pthread_setname_np (pthread_t thread, const char *name)
> +{
> +  char *oldname, *cp;
> +
> +  if (!pthread::is_good_object (&thread))
> +    return ESRCH;
> +
> +  cp = strdup(name);
               ^^^
              space?

> +  if (!cp)
> +    return ENOMEM;
> +
> +  oldname = thread->attr.name;
> +  thread->attr.name = cp;
> +
> +  if (oldname)
> +    free(oldname);
          ^^^
         space?

Looks good, otherwise.


Thanks,
Corinna

--
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH 2/2] Send thread names to debugger

Corinna Vinschen-2
In reply to this post by Jon TURNEY
On Jul 28 12:43, Jon Turney wrote:
> GDB with the patch from [1] can report and use these names.

This is still WIP, right?

> 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 <[hidden email]>
> ---
>  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);
                    ^^^         ^^^
                   space?      space?

Just wondering: Wouldn't it make sense to rename the internal threads
so they either always start with "cyg_" or with double underscore or
something like that to mark them as internal?  E.g.

  new cygthread (wait_sig, cygself, "cyg_wait_sig");

>        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);
                 ^^^                ^^^
                space?             space?

>  
>    (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");
                 ^^^                ^^^
                space?             space?

>    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)
> +//
/* */, please

> +
> +#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 */
                  ^^^
                 space?

> +      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);
                                              ^^^          ^^^
                                             space?       space?

> +}
> 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);
                    ^^^
                   space?

> +
>  #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");
                 ^^^                ^^^
                space?             space?



> +
>    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");
                    ^^^                ^^^
                   space?             space?

Since it's such a short function, why not just add a copy to profile.c
or just perform the RaiseException directly?

>  
>    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);
                 ^^^                ^^^
                space?             space?

> +
>    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);
                 ^^^                ^^^
                space?             space?

> +
>    if (oldname)
>      free(oldname);
          ^^^
         space?


Thanks,
Corinna

--
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH 1/2] Add pthread_getname_np and pthread_setname_np

Jon TURNEY
In reply to this post by Corinna Vinschen-2
On 28/07/2016 20:21, Corinna Vinschen wrote:

> Hi Jon,
>
> On Jul 28 12:43, Jon Turney wrote:
>> This patch adds pthread_getname_np and pthread_setname_np.
>>
>> These were added to glibc in 2.12[1] and are also present in some form on
>> NetBSD and several UNIXes.
>>
>> The code is based on NetBSD's implementation with changes to better match
>> Linux behaviour.
>>
>> Implementation quirks:
>>
>> * pthread_setname_np with a NULL pointer segfaults (as linux)
>>
>> * pthread_setname_np accepts names longer than 16 characters (linux returns
>> ERANGE)
>
> Given the behaviour of pthread_getname_np we should do the same, I think.

Ok.

>
>> * pthread_getname_np with a NULL pointer returns EFAULT (as linux)
>>
>> * pthread_getname_np with a buffer length of less than 16 returns ERANGE (as
>> linux)
>>
>> * pthread_getname_np truncates the thread name to fit the buffer length.
>> This guarantees success even when the default thread name is longer than 16
>> characters, but means there is no way to discover the actual length of the
>> thread name. (Linux always truncates the thread name to 16 characters)
>>
>> * Changing program_invocation_short_name changes the default thread name.
>>
>> I'll leave it up to you to decide any of these matter.
>>
>> This is implemented via class pthread_attr to make it easier to add
>> pthread_attr_[gs]etname_np (present in NetBSD and some UNIXes) should it
>> ever be added to Linux (or we decide we want it anyway).
>
> Good thinking.

Yaakov's idea, not mine :)

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH 2/2] Send thread names to debugger

Jon TURNEY
In reply to this post by Corinna Vinschen-2
On 28/07/2016 20:34, Corinna Vinschen wrote:
> On Jul 28 12:43, Jon Turney wrote:
>> GDB with the patch from [1] can report and use these names.
>
> This is still WIP, right?

Yes, that's right.

>> --- 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);
>                     ^^^         ^^^
>                    space?      space?
>
> Just wondering: Wouldn't it make sense to rename the internal threads
> so they either always start with "cyg_" or with double underscore or
> something like that to mark them as internal?  E.g.

Yeah, I wanted to do something like that.

But messing with the thread names may have other consequences (See
fhandler_tty.cc:109), and I was a bit wary of introducing a malloc/free
to into cygthread::create() to dynamically make the name with a "__"
prepended

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH 2/2] Send thread names to debugger

Corinna Vinschen-2
On Jul 29 14:17, Jon Turney wrote:

> On 28/07/2016 20:34, Corinna Vinschen wrote:
> > On Jul 28 12:43, Jon Turney wrote:
> > > GDB with the patch from [1] can report and use these names.
> >
> > This is still WIP, right?
>
> Yes, that's right.
>
> > > --- 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);
> >                     ^^^         ^^^
> >                    space?      space?
> >
> > Just wondering: Wouldn't it make sense to rename the internal threads
> > so they either always start with "cyg_" or with double underscore or
> > something like that to mark them as internal?  E.g.
>
> Yeah, I wanted to do something like that.
>
> But messing with the thread names may have other consequences (See
> fhandler_tty.cc:109), and I was a bit wary of introducing a malloc/free to
> into cygthread::create() to dynamically make the name with a "__" prepended
Ok.


Corinna

--
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

signature.asc (836 bytes) Download Attachment
Loading...