From c16eb6cf753d5df0779c284126d7356d2377fdb3 Mon Sep 17 00:00:00 2001 From: Sebastien GODARD Date: Mon, 22 Oct 2018 18:06:48 +0200 Subject: [PATCH] pidstat: Now handle processes with spaces in their name properly pidstat had a bug which made it unable to handle processes with spaces in their name, eg: $ cat /proc/5768/stat 5768 (Plex New Transc) S 1264 1252 1252 0 -1 1077960704 17317 0 18 0 9260 137 0 0 15 -5 8 0 1430749 186589184 16704 18446744073709551615 1 1 0 0 0 0 0 0 8404998 18446744073709551615 0 0 17 1 0 0 22 0 0 0 0 0 0 0 0 0 0 This patch fixes the problem. Reported by Chris Grindstaff (@cgrinds). Signed-off-by: Sebastien GODARD --- pidstat.c | 59 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/pidstat.c b/pidstat.c index bc22aa8..af48f29 100644 --- a/pidstat.c +++ b/pidstat.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -307,9 +308,10 @@ void read_proc_meminfo(void) int read_proc_pid_stat(unsigned int pid, struct pid_stats *pst, unsigned int *thread_nr, unsigned int tgid) { - FILE *fp; - char filename[128], format[256], comm[MAX_COMM_LEN + 1]; - size_t len; + int fd, sz, rc, commsz; + char filename[128]; + static char buffer[1024 + 1]; + char *start, *end; if (tgid) { sprintf(filename, TASK_STAT, tgid, pid); @@ -318,36 +320,45 @@ int read_proc_pid_stat(unsigned int pid, struct pid_stats *pst, sprintf(filename, PID_STAT, pid); } - if ((fp = fopen(filename, "r")) == NULL) + if ((fd = open(filename, O_RDONLY)) < 0) /* No such process */ return 1; - sprintf(format, "%%*d (%%%ds %%*s %%*d %%*d %%*d %%*d %%*d %%*u %%lu %%lu" - " %%lu %%lu %%lu %%lu %%lu %%lu %%*d %%*d %%u %%*u %%*d %%lu %%lu" - " %%*u %%*u %%*u %%*u %%*u %%*u %%*u %%*u %%*u %%*u %%*u %%*u %%*u" - " %%*u %%u %%*u %%*u %%*u %%lu %%lu\\n", MAX_COMM_LEN); - - fscanf(fp, format, comm, - &pst->minflt, &pst->cminflt, &pst->majflt, &pst->cmajflt, - &pst->utime, &pst->stime, &pst->cutime, &pst->cstime, - thread_nr, &pst->vsz, &pst->rss, &pst->processor, - &pst->gtime, &pst->cgtime); + sz = read(fd, buffer, 1024); + close(fd); + if (sz <= 0) + return 1; + buffer[sz] = '\0'; - fclose(fp); + if ((start = strchr(buffer, '(')) == NULL) + return 1; + start += 1; + if ((end = strrchr(start, ')')) == NULL) + return 1; + commsz = end - start; + if (commsz >= MAX_COMM_LEN) + return 1; + memcpy(pst->comm, start, commsz); + pst->comm[commsz] = '\0'; + start = end + 2; + + rc = sscanf(start, + "%*s %*d %*d %*d %*d %*d %*u %lu %lu" + " %lu %lu %lu %lu %ld %ld %*d %*d %u %*u %*d %lu %lu" + " %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u" + " %*u %u %*u %*u %*lu %lu %ld\n", + &pst->minflt, &pst->cminflt, &pst->majflt, &pst->cmajflt, + &pst->utime, &pst->stime, &pst->cutime, &pst->cstime, + thread_nr, &pst->vsz, &pst->rss, &pst->processor, + &pst->gtime, &pst->cgtime); + + if (rc < 14) + return 1; /* Convert to kB */ pst->vsz >>= 10; pst->rss = PG_TO_KB(pst->rss); - strncpy(pst->comm, comm, MAX_COMM_LEN); - pst->comm[MAX_COMM_LEN - 1] = '\0'; - - /* Remove trailing ')' */ - len = strlen(pst->comm); - if (len && (pst->comm[len - 1] == ')')) { - pst->comm[len - 1] = '\0'; - } - pst->pid = pid; pst->tgid = tgid; return 0; -- 2.14.4