From 9de89aecf352de831a0fee72d633a027f14c691a Mon Sep 17 00:00:00 2001 From: Craig Small Date: Sun, 29 Sep 2013 15:16:08 +1000 Subject: pstree shows threads correct names. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pstree would only show the process name, not the thread name. This change now makes pstree read /proc//task//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 | 1 + src/pstree.c | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index d9e2db0..845aa1d 100644 --- 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 ================ 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); -- cgit v1.2.3