diff options
author | Craig Small <csmall@enc.com.au> | 2013-09-29 15:16:08 +1000 |
---|---|---|
committer | Craig Small <csmall@enc.com.au> | 2013-09-29 15:16:08 +1000 |
commit | 9de89aecf352de831a0fee72d633a027f14c691a (patch) | |
tree | 2c97ed56b7db181b1454c43457588c72d0cfa68d | |
parent | ebf0be4cba460c11f3bfb8aa4393a7c49ed004ab (diff) |
pstree shows threads correct names.
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!
-rw-r--r-- | ChangeLog | 1 | ||||
-rw-r--r-- | src/pstree.c | 36 |
2 files changed, 31 insertions, 6 deletions
@@ -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 ================ diff --git a/src/pstree.c b/src/pstree.c index 82ac18f..2d5c05e 100644 --- a/src/pstree.c +++ b/src/pstree.c @@ -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); |