]> granicus.if.org Git - psmisc/commitdiff
pstree shows threads correct names.
authorCraig Small <csmall@enc.com.au>
Sun, 29 Sep 2013 05:16:08 +0000 (15:16 +1000)
committerCraig Small <csmall@enc.com.au>
Sun, 29 Sep 2013 05:16:08 +0000 (15:16 +1000)
pstree would only show the process name, not the thread name. This
change now makes pstree read /proc/<PID>/task/<TID>/stat to find the
threads' real names.
$ pstree -p 1187
udisksd(1187)─┬─{udisksd}(1189)
              ├─{udisksd}(1191)
              ├─{udisksd}(1192)
              ├─{udisksd}(1195)
              └─{udisksd}(27395)
./pstree -p 1187
udisksd(1187)─┬─{cleanup}(1195)
              ├─{gdbus}(1191)
              ├─{gmain}(1189)
              ├─{pool}(27395)
              └─{probing-thread}(1192)

References:
  https://sourceforge.net/p/psmisc/bugs/57/

This fix was made a lot easier due to Mapk providing a small test script
showing the broken behaviour, thanks!

ChangeLog
src/pstree.c

index d9e2db08f64665b40693b94e34b373fce617e64f..845aa1d48d62fad68763e492b56df1743f70c159 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,7 @@ Changes in 22.21
 ================
        * Missing comma in fuser(1) added Debian #702391
        * pstree uses COLUMN env variable Debian #717017
+       * pstree shows proper thread names SF Bug#57
 
 Changes in 22.20
 ================
index 82ac18fa0677eba33dc0ca1b3d2b6fe9b97c67c2..2d5c05e82905a9a93ed8369681de45640a7e98bd 100644 (file)
@@ -783,6 +783,33 @@ static void trim_tree_by_parent(PROC * current)
   trim_tree_by_parent(parent);
 }
 
+static char* get_threadname(const pid_t pid, const int tid, const char *comm)
+{
+    FILE *file;
+    char *thread_comm, *endcomm, *threadname;
+    char path[PATH_MAX + 1];
+    char readbuf[BUFSIZ + 1]; 
+
+    if (! (threadname = malloc(COMM_LEN + 2 + 1))) {
+       exit(2);
+    }
+    if (snprintf(path, PATH_MAX, "%s/%d/task/%d/stat", PROC_BASE, pid, tid) < 0)
+       perror("get_threadname: asprintf");
+    if ( (file = fopen(path, "r")) != NULL) {
+       if (fread(readbuf, 1, BUFSIZ, file) > 0) {
+           if ((thread_comm = strchr(readbuf, '('))
+                   && (endcomm = strrchr(thread_comm, ')'))) {
+               ++thread_comm;
+               *endcomm = '\0';
+               sprintf(threadname, "{%.*s}", COMM_LEN, thread_comm);
+               return threadname;
+           }
+       }
+    }
+    /* Fall back to old method */
+    sprintf(threadname, "{%.*s}", COMM_LEN, comm);
+    return threadname;
+}
 
 /*
  * read_proc now uses a similar method as procps for finding the process
@@ -859,7 +886,6 @@ static void read_proc(void)
               DIR *taskdir;
               struct dirent *dt;
               char *taskpath;
-              char *threadname;
               int thread;
 
               if (! (taskpath = malloc(strlen(path) + 10)))
@@ -868,23 +894,21 @@ static void read_proc(void)
 
               if ((taskdir = opendir(taskpath)) != 0) {
                 /* if we have this dir, we're on 2.6 */
-                if (! (threadname = malloc(COMM_LEN + 2 + 1))) {
-                    exit(2);
-                }
-                sprintf(threadname, "{%.*s}", COMM_LEN, comm);
                 while ((dt = readdir(taskdir)) != NULL) {
                   if ((thread = atoi(dt->d_name)) != 0) {
                     if (thread != pid) {
+                     char *threadname;
+                     threadname = get_threadname(pid, thread, comm);
                       if (print_args)
                         add_proc(threadname, thread, pid, pgid, st.st_uid, 
                             threadname, strlen (threadname) + 1, 1,scontext);
                       else
                         add_proc(threadname, thread, pid, pgid, st.st_uid, 
                             NULL, 0, 1, scontext);
+                      free(threadname);
                       }
                     }
                   }
-                  free(threadname);
                   (void) closedir(taskdir);
                 }
               free(taskpath);