On 07.11.2012 16:54, Matthias Schwarzott wrote:
Hi!

I wonder if it would be good to have valgrind remember the names of the
threads.

Here is a first implementation of this change.
It just enhances the struct ThreadState by a char array thread_name.
The handler of prctl writes its argument there.
For the first thread it is initialized to "main" (without valgrind there is the name of the executable by default, how could I get this).

pp_Error prints Errors like this (if thread name is there):
Thread 2 abcdxyz01234567:

gdbserver appends it at the end for the qThreadExtraInfo query.
(gdb) info threads
  Id   Target Id         Frame
* 2 Thread 30698 (tid 2 VgTs_Runnable abcdxyz01234567) 0x00000000004009aa in child_fn (arg=0x0) at threadname.c:32 1 Thread 30679 (tid 1 VgTs_Yielding main) 0x00000034cfae88d1 in clone () from /lib64/libc.so.6

The testcase I started to write is also included.

Regards
Matthias
commit 56074382acdf0eb5f77c08aaec7b65a877658823
Author: Matthias Schwarzott <z...@gentoo.org>
Date:   Tue Oct 30 20:39:21 2012 +0100

    set thread name

diff --git a/coregrind/m_errormgr.c b/coregrind/m_errormgr.c
index b4fec57..066056b 100644
--- a/coregrind/m_errormgr.c
+++ b/coregrind/m_errormgr.c
@@ -603,7 +603,12 @@ static void pp_Error ( Error* err, Bool allow_db_attach, Bool xml )
 
       if (VG_(tdict).tool_show_ThreadIDs_for_errors
           && err->tid > 0 && err->tid != last_tid_printed) {
-         VG_(umsg)("Thread %d:\n", err->tid );
+	 ThreadState* tst = VG_(get_ThreadState)(err->tid);
+	 if (tst->thread_name[0]) {
+            VG_(umsg)("Thread %d %s:\n", err->tid, VG_(get_ThreadState)(err->tid)->thread_name);
+	 } else {
+            VG_(umsg)("Thread %d:\n", err->tid );
+	 }
          last_tid_printed = err->tid;
       }
    
diff --git a/coregrind/m_gdbserver/server.c b/coregrind/m_gdbserver/server.c
index 5dcb139..277ba59 100644
--- a/coregrind/m_gdbserver/server.c
+++ b/coregrind/m_gdbserver/server.c
@@ -499,9 +499,16 @@ void handle_query (char *arg_own_buf, int *new_packet_len_p)
       if (ti != NULL) {
          tst = (ThreadState *) inferior_target_data (ti);
          /* Additional info is the tid and the thread status. */
+	 if (tst->thread_name[0]) {
+         VG_(snprintf) (status, sizeof(status), "tid %d %s %s",
+                        tst->tid, 
+                        VG_(name_of_ThreadStatus)(tst->status),
+	 		tst->thread_name);
+	 } else {
          VG_(snprintf) (status, sizeof(status), "tid %d %s",
                         tst->tid, 
                         VG_(name_of_ThreadStatus)(tst->status));
+	 }
          hexify (arg_own_buf, status, strlen(status));
          return;
       } else {
diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c
index ef41c64..56feac2 100644
--- a/coregrind/m_scheduler/scheduler.c
+++ b/coregrind/m_scheduler/scheduler.c
@@ -236,6 +236,7 @@ ThreadId VG_(alloc_ThreadState) ( void )
       if (VG_(threads)[i].status == VgTs_Empty) {
 	 VG_(threads)[i].status = VgTs_Init;
 	 VG_(threads)[i].exitreason = VgSrc_None;
+	 VG_(threads)[i].thread_name[0] = 0;
          return i;
       }
    }
@@ -614,6 +615,7 @@ ThreadId VG_(scheduler_init_phase1) ( void )
    }
 
    tid_main = VG_(alloc_ThreadState)();
+   VG_(strncpy)(VG_(threads)[tid_main].thread_name, "main", sizeof(VG_(threads)[tid_main].thread_name));
 
    /* Bleh.  Unfortunately there are various places in the system that
       assume that the main thread has a ThreadId of 1.
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index 7c94bd5..6cde946 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -939,6 +939,13 @@ POST(sys_prctl)
    case VKI_PR_GET_FPEXC:
       POST_MEM_WRITE(ARG2, sizeof(Int));
       break;
+   case VKI_PR_SET_NAME:
+      {
+         ThreadState* tst = VG_(get_ThreadState)(tid);
+         VG_(strncpy)(tst->thread_name, (char*)ARG2, 16);
+	 tst->thread_name[16] = 0;
+      }
+      break;
    case VKI_PR_GET_NAME:
       POST_MEM_WRITE(ARG2, VKI_TASK_COMM_LEN);
       break;
diff --git a/coregrind/pub_core_threadstate.h b/coregrind/pub_core_threadstate.h
index 0bd9927..73ee947 100644
--- a/coregrind/pub_core_threadstate.h
+++ b/coregrind/pub_core_threadstate.h
@@ -353,6 +353,8 @@ typedef struct {
    /* Per-thread jmp_buf to resume scheduler after a signal */
    Bool               sched_jmpbuf_valid;
    VG_MINIMAL_JMP_BUF(sched_jmpbuf);
+   
+   char thread_name[17];
 }
 ThreadState;
 
diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am
index cf1d5cc..4bfce22 100644
--- a/memcheck/tests/Makefile.am
+++ b/memcheck/tests/Makefile.am
@@ -228,7 +228,8 @@ EXTRA_DIST = \
 	wrap8.vgtest wrap8.stdout.exp wrap8.stderr.exp \
 	wrap8.stdout.exp2 wrap8.stderr.exp2 \
 	writev1.stderr.exp writev1.vgtest \
-	xml1.stderr.exp xml1.stdout.exp xml1.vgtest xml1.stderr.exp-s390x-mvc
+	xml1.stderr.exp xml1.stdout.exp xml1.vgtest xml1.stderr.exp-s390x-mvc \
+	threadname.vgtest
 
 check_PROGRAMS = \
 	accounting \
@@ -296,7 +297,8 @@ check_PROGRAMS = \
 	vcpu_fbench vcpu_fnfns \
 	xml1 \
 	wrap1 wrap2 wrap3 wrap4 wrap5 wrap6 wrap7 wrap7so.so wrap8 \
-	writev1
+	writev1 \
+	threadname
 
 if DWARF4
 check_PROGRAMS += dw4
@@ -323,6 +325,7 @@ dw4_CFLAGS		= $(AM_CFLAGS) -gdwarf-4 -fdebug-types-section
 
 err_disable3_LDADD 	= -lpthread
 err_disable4_LDADD 	= -lpthread
+threadname_LDADD 	= -lpthread
 
 error_counts_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_UNINITIALIZED@
 
diff --git a/memcheck/tests/threadname.c b/memcheck/tests/threadname.c
new file mode 100644
index 0000000..b8366de
--- /dev/null
+++ b/memcheck/tests/threadname.c
@@ -0,0 +1,54 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <pthread.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <assert.h>
+
+void* child_fn ( void* arg )
+{
+	pthread_setname_np(pthread_self(), "");
+	pthread_setname_np(pthread_self(), "a");
+	pthread_setname_np(pthread_self(), "ab");
+	pthread_setname_np(pthread_self(), "abc");
+	pthread_setname_np(pthread_self(), "abcd");
+	pthread_setname_np(pthread_self(), "abcdx");
+	pthread_setname_np(pthread_self(), "abcdxy");
+	pthread_setname_np(pthread_self(), "abcdxyz");
+	pthread_setname_np(pthread_self(), "abcdxyz0");
+	pthread_setname_np(pthread_self(), "abcdxyz01");
+	pthread_setname_np(pthread_self(), "abcdxyz012");
+	pthread_setname_np(pthread_self(), "abcdxyz0123");
+	pthread_setname_np(pthread_self(), "abcdxyz01234");
+	pthread_setname_np(pthread_self(), "abcdxyz012345");
+	pthread_setname_np(pthread_self(), "abcdxyz0123456");
+	pthread_setname_np(pthread_self(), "abcdxyz01234567");
+	pthread_setname_np(pthread_self(), "abcdxyz012345678");
+	pthread_setname_np(pthread_self(), "abcdxyz0123456789");
+	int* m = malloc(sizeof(int));
+	m[2]=0;
+	free(m);
+	return NULL;
+}
+
+int main(int argc, const char** argv)
+{
+	int r;
+	pthread_t child;
+	int* o = malloc(sizeof(int));
+	o[1]=0;
+	free(o);
+	r = pthread_create(&child, NULL, child_fn, NULL);
+	assert(!r);
+	sleep(1);
+	r = pthread_join(child, NULL);
+	assert(!r);
+	o = malloc(sizeof(int));
+	o[1]=0;
+	free(o);
+	return 0;
+}
+
diff --git a/memcheck/tests/threadname.vgtest b/memcheck/tests/threadname.vgtest
new file mode 100644
index 0000000..01b0d43
--- /dev/null
+++ b/memcheck/tests/threadname.vgtest
@@ -0,0 +1 @@
+prog: threadname
------------------------------------------------------------------------------
Monitor your physical, virtual and cloud infrastructure from a single
web console. Get in-depth insight into apps, servers, databases, vmware,
SAP, cloud infrastructure, etc. Download 30-day Free Trial.
Pricing starts from $795 for 25 servers or applications!
http://p.sf.net/sfu/zoho_dev2dev_nov
_______________________________________________
Valgrind-users mailing list
Valgrind-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/valgrind-users

Reply via email to