summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCraig Small <csmall@enc.com.au>2013-09-29 15:16:08 +1000
committerCraig Small <csmall@enc.com.au>2013-09-29 15:16:08 +1000
commit9de89aecf352de831a0fee72d633a027f14c691a (patch)
tree2c97ed56b7db181b1454c43457588c72d0cfa68d
parentebf0be4cba460c11f3bfb8aa4393a7c49ed004ab (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--ChangeLog1
-rw-r--r--src/pstree.c36
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);