pidof/killall: fix bug 625 (kernel threads get stale "binary name")

function                                             old     new   delta
procps_scan                                         1622    1642     +20

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2009-09-22 23:06:07 +02:00
parent 200d522fb8
commit ed4ff0e8cb

View File

@ -138,8 +138,8 @@ static unsigned long fast_strtoul_16(char **endptr)
return n; return n;
} }
/* TOPMEM uses fast_strtoul_10, so... */ /* TOPMEM uses fast_strtoul_10, so... */
#undef ENABLE_FEATURE_FAST_TOP # undef ENABLE_FEATURE_FAST_TOP
#define ENABLE_FEATURE_FAST_TOP 1 # define ENABLE_FEATURE_FAST_TOP 1
#endif #endif
#if ENABLE_FEATURE_FAST_TOP #if ENABLE_FEATURE_FAST_TOP
@ -223,14 +223,16 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
} }
#endif #endif
/* After this point we have to break, not continue /* After this point we can:
* ("continue" would mean that current /proc/NNN * "break": stop parsing, return the data
* is not a valid process info) */ * "continue": try next /proc/XXX
*/
memset(&sp->vsz, 0, sizeof(*sp) - offsetof(procps_status_t, vsz)); memset(&sp->vsz, 0, sizeof(*sp) - offsetof(procps_status_t, vsz));
sp->pid = pid; sp->pid = pid;
if (!(flags & ~PSSCAN_PID)) break; if (!(flags & ~PSSCAN_PID))
break; /* we needed only pid, we got it */
#if ENABLE_SELINUX #if ENABLE_SELINUX
if (flags & PSSCAN_CONTEXT) { if (flags & PSSCAN_CONTEXT) {
@ -243,7 +245,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
if (flags & PSSCAN_UIDGID) { if (flags & PSSCAN_UIDGID) {
if (stat(filename, &sb)) if (stat(filename, &sb))
break; continue; /* process probably exited */
/* Effective UID/GID, not real */ /* Effective UID/GID, not real */
sp->uid = sb.st_uid; sp->uid = sb.st_uid;
sp->gid = sb.st_gid; sp->gid = sb.st_gid;
@ -259,10 +261,10 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
strcpy(filename_tail, "stat"); strcpy(filename_tail, "stat");
n = read_to_buf(filename, buf); n = read_to_buf(filename, buf);
if (n < 0) if (n < 0)
break; continue; /* process probably exited */
cp = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */ cp = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */
/*if (!cp || cp[1] != ' ') /*if (!cp || cp[1] != ' ')
break;*/ continue;*/
cp[0] = '\0'; cp[0] = '\0';
if (sizeof(sp->comm) < 16) if (sizeof(sp->comm) < 16)
BUG_comm_size(); BUG_comm_size();
@ -282,12 +284,12 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
"%lu " /* start_time */ "%lu " /* start_time */
"%lu " /* vsize */ "%lu " /* vsize */
"%lu " /* rss */ "%lu " /* rss */
#if ENABLE_FEATURE_TOP_SMP_PROCESS # if ENABLE_FEATURE_TOP_SMP_PROCESS
"%*s %*s %*s %*s %*s %*s " /*rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */ "%*s %*s %*s %*s %*s %*s " /*rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */
"%*s %*s %*s %*s " /*signal, blocked, sigignore, sigcatch */ "%*s %*s %*s %*s " /*signal, blocked, sigignore, sigcatch */
"%*s %*s %*s %*s " /*wchan, nswap, cnswap, exit_signal */ "%*s %*s %*s %*s " /*wchan, nswap, cnswap, exit_signal */
"%d" /*cpu last seen on*/ "%d" /*cpu last seen on*/
#endif # endif
, ,
sp->state, &sp->ppid, sp->state, &sp->ppid,
&sp->pgid, &sp->sid, &tty, &sp->pgid, &sp->sid, &tty,
@ -296,17 +298,17 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
&sp->start_time, &sp->start_time,
&vsz, &vsz,
&rss &rss
#if ENABLE_FEATURE_TOP_SMP_PROCESS # if ENABLE_FEATURE_TOP_SMP_PROCESS
, &sp->last_seen_on_cpu , &sp->last_seen_on_cpu
#endif # endif
); );
if (n < 11) if (n < 11)
break; continue; /* bogus data, get next /proc/XXX */
#if ENABLE_FEATURE_TOP_SMP_PROCESS # if ENABLE_FEATURE_TOP_SMP_PROCESS
if (n < 11+15) if (n < 11+15)
sp->last_seen_on_cpu = 0; sp->last_seen_on_cpu = 0;
#endif # endif
/* vsz is in bytes and we want kb */ /* vsz is in bytes and we want kb */
sp->vsz = vsz >> 10; sp->vsz = vsz >> 10;
@ -336,14 +338,14 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
sp->vsz = fast_strtoul_10(&cp) >> 10; sp->vsz = fast_strtoul_10(&cp) >> 10;
/* vsz is in bytes but rss is in *PAGES*! Can you believe that? */ /* vsz is in bytes but rss is in *PAGES*! Can you believe that? */
sp->rss = fast_strtoul_10(&cp) << sp->shift_pages_to_kb; sp->rss = fast_strtoul_10(&cp) << sp->shift_pages_to_kb;
#if ENABLE_FEATURE_TOP_SMP_PROCESS # if ENABLE_FEATURE_TOP_SMP_PROCESS
/* (6): rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */ /* (6): rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */
/* (4): signal, blocked, sigignore, sigcatch */ /* (4): signal, blocked, sigignore, sigcatch */
/* (4): wchan, nswap, cnswap, exit_signal */ /* (4): wchan, nswap, cnswap, exit_signal */
cp = skip_fields(cp, 14); cp = skip_fields(cp, 14);
//FIXME: is it safe to assume this field exists? //FIXME: is it safe to assume this field exists?
sp->last_seen_on_cpu = fast_strtoul_10(&cp); sp->last_seen_on_cpu = fast_strtoul_10(&cp);
#endif # endif
#endif /* end of !ENABLE_FEATURE_TOP_SMP_PROCESS */ #endif /* end of !ENABLE_FEATURE_TOP_SMP_PROCESS */
#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS #if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS
@ -368,48 +370,48 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
strcpy(filename_tail, "smaps"); strcpy(filename_tail, "smaps");
file = fopen_for_read(filename); file = fopen_for_read(filename);
if (!file) if (file) {
break; while (fgets(buf, sizeof(buf), file)) {
while (fgets(buf, sizeof(buf), file)) { unsigned long sz;
unsigned long sz; char *tp;
char *tp; char w;
char w;
#define SCAN(str, name) \ #define SCAN(str, name) \
if (strncmp(buf, str, sizeof(str)-1) == 0) { \ if (strncmp(buf, str, sizeof(str)-1) == 0) { \
tp = skip_whitespace(buf + sizeof(str)-1); \ tp = skip_whitespace(buf + sizeof(str)-1); \
sp->name += fast_strtoul_10(&tp); \ sp->name += fast_strtoul_10(&tp); \
continue; \ continue; \
} }
SCAN("Shared_Clean:" , shared_clean ); SCAN("Shared_Clean:" , shared_clean );
SCAN("Shared_Dirty:" , shared_dirty ); SCAN("Shared_Dirty:" , shared_dirty );
SCAN("Private_Clean:", private_clean); SCAN("Private_Clean:", private_clean);
SCAN("Private_Dirty:", private_dirty); SCAN("Private_Dirty:", private_dirty);
#undef SCAN #undef SCAN
// f7d29000-f7d39000 rw-s ADR M:m OFS FILE // f7d29000-f7d39000 rw-s ADR M:m OFS FILE
tp = strchr(buf, '-'); tp = strchr(buf, '-');
if (tp) { if (tp) {
*tp = ' '; *tp = ' ';
tp = buf; tp = buf;
sz = fast_strtoul_16(&tp); /* start */ sz = fast_strtoul_16(&tp); /* start */
sz = (fast_strtoul_16(&tp) - sz) >> 10; /* end - start */ sz = (fast_strtoul_16(&tp) - sz) >> 10; /* end - start */
// tp -> "rw-s" string // tp -> "rw-s" string
w = tp[1]; w = tp[1];
// skipping "rw-s ADR M:m OFS " // skipping "rw-s ADR M:m OFS "
tp = skip_whitespace(skip_fields(tp, 4)); tp = skip_whitespace(skip_fields(tp, 4));
// filter out /dev/something (something != zero) // filter out /dev/something (something != zero)
if (strncmp(tp, "/dev/", 5) != 0 || strcmp(tp, "/dev/zero\n") == 0) { if (strncmp(tp, "/dev/", 5) != 0 || strcmp(tp, "/dev/zero\n") == 0) {
if (w == 'w') { if (w == 'w') {
sp->mapped_rw += sz; sp->mapped_rw += sz;
} else if (w == '-') { } else if (w == '-') {
sp->mapped_ro += sz; sp->mapped_ro += sz;
}
} }
}
//else printf("DROPPING %s (%s)\n", buf, tp); //else printf("DROPPING %s (%s)\n", buf, tp);
if (strcmp(tp, "[stack]\n") == 0) if (strcmp(tp, "[stack]\n") == 0)
sp->stack += sz; sp->stack += sz;
}
} }
fclose(file);
} }
fclose(file);
} }
#endif /* TOPMEM */ #endif /* TOPMEM */
#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS #if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS
@ -418,23 +420,34 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
strcpy(filename_tail, "status"); strcpy(filename_tail, "status");
file = fopen_for_read(filename); file = fopen_for_read(filename);
if (!file) if (file) {
break; while (fgets(buf, sizeof(buf), file)) {
while (fgets(buf, sizeof(buf), file)) { char *tp;
char *tp;
#define SCAN_TWO(str, name, statement) \ #define SCAN_TWO(str, name, statement) \
if (strncmp(buf, str, sizeof(str)-1) == 0) { \ if (strncmp(buf, str, sizeof(str)-1) == 0) { \
tp = skip_whitespace(buf + sizeof(str)-1); \ tp = skip_whitespace(buf + sizeof(str)-1); \
sscanf(tp, "%u", &sp->name); \ sscanf(tp, "%u", &sp->name); \
statement; \ statement; \
} }
SCAN_TWO("Uid:", ruid, continue); SCAN_TWO("Uid:", ruid, continue);
SCAN_TWO("Gid:", rgid, break); SCAN_TWO("Gid:", rgid, break);
#undef SCAN_TWO #undef SCAN_TWO
}
fclose(file);
} }
fclose(file);
} }
#endif /* PS_ADDITIONAL_COLUMNS */ #endif /* PS_ADDITIONAL_COLUMNS */
if (flags & PSSCAN_EXE) {
strcpy(filename_tail, "exe");
free(sp->exe);
sp->exe = xmalloc_readlink(filename);
}
/* Note: if /proc/PID/cmdline is empty,
* code below "breaks". Therefore it must be
* the last code to parse /proc/PID/xxx data
* (we used to have /proc/PID/exe parsing after it
* and were getting stale sp->exe).
*/
#if 0 /* PSSCAN_CMD is not used */ #if 0 /* PSSCAN_CMD is not used */
if (flags & (PSSCAN_CMD|PSSCAN_ARGV0)) { if (flags & (PSSCAN_CMD|PSSCAN_ARGV0)) {
free(sp->argv0); free(sp->argv0);
@ -477,13 +490,9 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
} }
} }
#endif #endif
if (flags & PSSCAN_EXE) {
strcpy(filename_tail, "exe");
free(sp->exe);
sp->exe = xmalloc_readlink(filename);
}
break; break;
} } /* for (;;) */
return sp; return sp;
} }