diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-09-22 23:06:07 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-09-22 23:06:07 +0200 |
commit | ed4ff0e8cbe8b330ecc9c51d0c5ff2ad1647ad5d (patch) | |
tree | 07a10f1bfdee005231cd17a230d9e4fbf5857483 /libbb | |
parent | 200d522fb85c24dd1ed36e5fcc29c1140b8b428b (diff) | |
download | busybox-w32-ed4ff0e8cbe8b330ecc9c51d0c5ff2ad1647ad5d.tar.gz busybox-w32-ed4ff0e8cbe8b330ecc9c51d0c5ff2ad1647ad5d.tar.bz2 busybox-w32-ed4ff0e8cbe8b330ecc9c51d0c5ff2ad1647ad5d.zip |
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>
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/procps.c | 133 |
1 files changed, 71 insertions, 62 deletions
diff --git a/libbb/procps.c b/libbb/procps.c index 845a2141b..48e60a792 100644 --- a/libbb/procps.c +++ b/libbb/procps.c | |||
@@ -138,8 +138,8 @@ static unsigned long fast_strtoul_16(char **endptr) | |||
138 | return n; | 138 | return n; |
139 | } | 139 | } |
140 | /* TOPMEM uses fast_strtoul_10, so... */ | 140 | /* TOPMEM uses fast_strtoul_10, so... */ |
141 | #undef ENABLE_FEATURE_FAST_TOP | 141 | # undef ENABLE_FEATURE_FAST_TOP |
142 | #define ENABLE_FEATURE_FAST_TOP 1 | 142 | # define ENABLE_FEATURE_FAST_TOP 1 |
143 | #endif | 143 | #endif |
144 | 144 | ||
145 | #if ENABLE_FEATURE_FAST_TOP | 145 | #if ENABLE_FEATURE_FAST_TOP |
@@ -223,14 +223,16 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) | |||
223 | } | 223 | } |
224 | #endif | 224 | #endif |
225 | 225 | ||
226 | /* After this point we have to break, not continue | 226 | /* After this point we can: |
227 | * ("continue" would mean that current /proc/NNN | 227 | * "break": stop parsing, return the data |
228 | * is not a valid process info) */ | 228 | * "continue": try next /proc/XXX |
229 | */ | ||
229 | 230 | ||
230 | memset(&sp->vsz, 0, sizeof(*sp) - offsetof(procps_status_t, vsz)); | 231 | memset(&sp->vsz, 0, sizeof(*sp) - offsetof(procps_status_t, vsz)); |
231 | 232 | ||
232 | sp->pid = pid; | 233 | sp->pid = pid; |
233 | if (!(flags & ~PSSCAN_PID)) break; | 234 | if (!(flags & ~PSSCAN_PID)) |
235 | break; /* we needed only pid, we got it */ | ||
234 | 236 | ||
235 | #if ENABLE_SELINUX | 237 | #if ENABLE_SELINUX |
236 | if (flags & PSSCAN_CONTEXT) { | 238 | if (flags & PSSCAN_CONTEXT) { |
@@ -243,7 +245,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) | |||
243 | 245 | ||
244 | if (flags & PSSCAN_UIDGID) { | 246 | if (flags & PSSCAN_UIDGID) { |
245 | if (stat(filename, &sb)) | 247 | if (stat(filename, &sb)) |
246 | break; | 248 | continue; /* process probably exited */ |
247 | /* Effective UID/GID, not real */ | 249 | /* Effective UID/GID, not real */ |
248 | sp->uid = sb.st_uid; | 250 | sp->uid = sb.st_uid; |
249 | sp->gid = sb.st_gid; | 251 | sp->gid = sb.st_gid; |
@@ -259,10 +261,10 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) | |||
259 | strcpy(filename_tail, "stat"); | 261 | strcpy(filename_tail, "stat"); |
260 | n = read_to_buf(filename, buf); | 262 | n = read_to_buf(filename, buf); |
261 | if (n < 0) | 263 | if (n < 0) |
262 | break; | 264 | continue; /* process probably exited */ |
263 | cp = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */ | 265 | cp = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */ |
264 | /*if (!cp || cp[1] != ' ') | 266 | /*if (!cp || cp[1] != ' ') |
265 | break;*/ | 267 | continue;*/ |
266 | cp[0] = '\0'; | 268 | cp[0] = '\0'; |
267 | if (sizeof(sp->comm) < 16) | 269 | if (sizeof(sp->comm) < 16) |
268 | BUG_comm_size(); | 270 | BUG_comm_size(); |
@@ -282,12 +284,12 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) | |||
282 | "%lu " /* start_time */ | 284 | "%lu " /* start_time */ |
283 | "%lu " /* vsize */ | 285 | "%lu " /* vsize */ |
284 | "%lu " /* rss */ | 286 | "%lu " /* rss */ |
285 | #if ENABLE_FEATURE_TOP_SMP_PROCESS | 287 | # if ENABLE_FEATURE_TOP_SMP_PROCESS |
286 | "%*s %*s %*s %*s %*s %*s " /*rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */ | 288 | "%*s %*s %*s %*s %*s %*s " /*rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */ |
287 | "%*s %*s %*s %*s " /*signal, blocked, sigignore, sigcatch */ | 289 | "%*s %*s %*s %*s " /*signal, blocked, sigignore, sigcatch */ |
288 | "%*s %*s %*s %*s " /*wchan, nswap, cnswap, exit_signal */ | 290 | "%*s %*s %*s %*s " /*wchan, nswap, cnswap, exit_signal */ |
289 | "%d" /*cpu last seen on*/ | 291 | "%d" /*cpu last seen on*/ |
290 | #endif | 292 | # endif |
291 | , | 293 | , |
292 | sp->state, &sp->ppid, | 294 | sp->state, &sp->ppid, |
293 | &sp->pgid, &sp->sid, &tty, | 295 | &sp->pgid, &sp->sid, &tty, |
@@ -296,17 +298,17 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) | |||
296 | &sp->start_time, | 298 | &sp->start_time, |
297 | &vsz, | 299 | &vsz, |
298 | &rss | 300 | &rss |
299 | #if ENABLE_FEATURE_TOP_SMP_PROCESS | 301 | # if ENABLE_FEATURE_TOP_SMP_PROCESS |
300 | , &sp->last_seen_on_cpu | 302 | , &sp->last_seen_on_cpu |
301 | #endif | 303 | # endif |
302 | ); | 304 | ); |
303 | 305 | ||
304 | if (n < 11) | 306 | if (n < 11) |
305 | break; | 307 | continue; /* bogus data, get next /proc/XXX */ |
306 | #if ENABLE_FEATURE_TOP_SMP_PROCESS | 308 | # if ENABLE_FEATURE_TOP_SMP_PROCESS |
307 | if (n < 11+15) | 309 | if (n < 11+15) |
308 | sp->last_seen_on_cpu = 0; | 310 | sp->last_seen_on_cpu = 0; |
309 | #endif | 311 | # endif |
310 | 312 | ||
311 | /* vsz is in bytes and we want kb */ | 313 | /* vsz is in bytes and we want kb */ |
312 | sp->vsz = vsz >> 10; | 314 | sp->vsz = vsz >> 10; |
@@ -336,14 +338,14 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) | |||
336 | sp->vsz = fast_strtoul_10(&cp) >> 10; | 338 | sp->vsz = fast_strtoul_10(&cp) >> 10; |
337 | /* vsz is in bytes but rss is in *PAGES*! Can you believe that? */ | 339 | /* vsz is in bytes but rss is in *PAGES*! Can you believe that? */ |
338 | sp->rss = fast_strtoul_10(&cp) << sp->shift_pages_to_kb; | 340 | sp->rss = fast_strtoul_10(&cp) << sp->shift_pages_to_kb; |
339 | #if ENABLE_FEATURE_TOP_SMP_PROCESS | 341 | # if ENABLE_FEATURE_TOP_SMP_PROCESS |
340 | /* (6): rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */ | 342 | /* (6): rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */ |
341 | /* (4): signal, blocked, sigignore, sigcatch */ | 343 | /* (4): signal, blocked, sigignore, sigcatch */ |
342 | /* (4): wchan, nswap, cnswap, exit_signal */ | 344 | /* (4): wchan, nswap, cnswap, exit_signal */ |
343 | cp = skip_fields(cp, 14); | 345 | cp = skip_fields(cp, 14); |
344 | //FIXME: is it safe to assume this field exists? | 346 | //FIXME: is it safe to assume this field exists? |
345 | sp->last_seen_on_cpu = fast_strtoul_10(&cp); | 347 | sp->last_seen_on_cpu = fast_strtoul_10(&cp); |
346 | #endif | 348 | # endif |
347 | #endif /* end of !ENABLE_FEATURE_TOP_SMP_PROCESS */ | 349 | #endif /* end of !ENABLE_FEATURE_TOP_SMP_PROCESS */ |
348 | 350 | ||
349 | #if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS | 351 | #if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS |
@@ -368,48 +370,48 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) | |||
368 | 370 | ||
369 | strcpy(filename_tail, "smaps"); | 371 | strcpy(filename_tail, "smaps"); |
370 | file = fopen_for_read(filename); | 372 | file = fopen_for_read(filename); |
371 | if (!file) | 373 | if (file) { |
372 | break; | 374 | while (fgets(buf, sizeof(buf), file)) { |
373 | while (fgets(buf, sizeof(buf), file)) { | 375 | unsigned long sz; |
374 | unsigned long sz; | 376 | char *tp; |
375 | char *tp; | 377 | char w; |
376 | char w; | ||
377 | #define SCAN(str, name) \ | 378 | #define SCAN(str, name) \ |
378 | if (strncmp(buf, str, sizeof(str)-1) == 0) { \ | 379 | if (strncmp(buf, str, sizeof(str)-1) == 0) { \ |
379 | tp = skip_whitespace(buf + sizeof(str)-1); \ | 380 | tp = skip_whitespace(buf + sizeof(str)-1); \ |
380 | sp->name += fast_strtoul_10(&tp); \ | 381 | sp->name += fast_strtoul_10(&tp); \ |
381 | continue; \ | 382 | continue; \ |
382 | } | 383 | } |
383 | SCAN("Shared_Clean:" , shared_clean ); | 384 | SCAN("Shared_Clean:" , shared_clean ); |
384 | SCAN("Shared_Dirty:" , shared_dirty ); | 385 | SCAN("Shared_Dirty:" , shared_dirty ); |
385 | SCAN("Private_Clean:", private_clean); | 386 | SCAN("Private_Clean:", private_clean); |
386 | SCAN("Private_Dirty:", private_dirty); | 387 | SCAN("Private_Dirty:", private_dirty); |
387 | #undef SCAN | 388 | #undef SCAN |
388 | // f7d29000-f7d39000 rw-s ADR M:m OFS FILE | 389 | // f7d29000-f7d39000 rw-s ADR M:m OFS FILE |
389 | tp = strchr(buf, '-'); | 390 | tp = strchr(buf, '-'); |
390 | if (tp) { | 391 | if (tp) { |
391 | *tp = ' '; | 392 | *tp = ' '; |
392 | tp = buf; | 393 | tp = buf; |
393 | sz = fast_strtoul_16(&tp); /* start */ | 394 | sz = fast_strtoul_16(&tp); /* start */ |
394 | sz = (fast_strtoul_16(&tp) - sz) >> 10; /* end - start */ | 395 | sz = (fast_strtoul_16(&tp) - sz) >> 10; /* end - start */ |
395 | // tp -> "rw-s" string | 396 | // tp -> "rw-s" string |
396 | w = tp[1]; | 397 | w = tp[1]; |
397 | // skipping "rw-s ADR M:m OFS " | 398 | // skipping "rw-s ADR M:m OFS " |
398 | tp = skip_whitespace(skip_fields(tp, 4)); | 399 | tp = skip_whitespace(skip_fields(tp, 4)); |
399 | // filter out /dev/something (something != zero) | 400 | // filter out /dev/something (something != zero) |
400 | if (strncmp(tp, "/dev/", 5) != 0 || strcmp(tp, "/dev/zero\n") == 0) { | 401 | if (strncmp(tp, "/dev/", 5) != 0 || strcmp(tp, "/dev/zero\n") == 0) { |
401 | if (w == 'w') { | 402 | if (w == 'w') { |
402 | sp->mapped_rw += sz; | 403 | sp->mapped_rw += sz; |
403 | } else if (w == '-') { | 404 | } else if (w == '-') { |
404 | sp->mapped_ro += sz; | 405 | sp->mapped_ro += sz; |
406 | } | ||
405 | } | 407 | } |
406 | } | ||
407 | //else printf("DROPPING %s (%s)\n", buf, tp); | 408 | //else printf("DROPPING %s (%s)\n", buf, tp); |
408 | if (strcmp(tp, "[stack]\n") == 0) | 409 | if (strcmp(tp, "[stack]\n") == 0) |
409 | sp->stack += sz; | 410 | sp->stack += sz; |
411 | } | ||
410 | } | 412 | } |
413 | fclose(file); | ||
411 | } | 414 | } |
412 | fclose(file); | ||
413 | } | 415 | } |
414 | #endif /* TOPMEM */ | 416 | #endif /* TOPMEM */ |
415 | #if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS | 417 | #if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS |
@@ -418,23 +420,34 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) | |||
418 | 420 | ||
419 | strcpy(filename_tail, "status"); | 421 | strcpy(filename_tail, "status"); |
420 | file = fopen_for_read(filename); | 422 | file = fopen_for_read(filename); |
421 | if (!file) | 423 | if (file) { |
422 | break; | 424 | while (fgets(buf, sizeof(buf), file)) { |
423 | while (fgets(buf, sizeof(buf), file)) { | 425 | char *tp; |
424 | char *tp; | ||
425 | #define SCAN_TWO(str, name, statement) \ | 426 | #define SCAN_TWO(str, name, statement) \ |
426 | if (strncmp(buf, str, sizeof(str)-1) == 0) { \ | 427 | if (strncmp(buf, str, sizeof(str)-1) == 0) { \ |
427 | tp = skip_whitespace(buf + sizeof(str)-1); \ | 428 | tp = skip_whitespace(buf + sizeof(str)-1); \ |
428 | sscanf(tp, "%u", &sp->name); \ | 429 | sscanf(tp, "%u", &sp->name); \ |
429 | statement; \ | 430 | statement; \ |
430 | } | 431 | } |
431 | SCAN_TWO("Uid:", ruid, continue); | 432 | SCAN_TWO("Uid:", ruid, continue); |
432 | SCAN_TWO("Gid:", rgid, break); | 433 | SCAN_TWO("Gid:", rgid, break); |
433 | #undef SCAN_TWO | 434 | #undef SCAN_TWO |
435 | } | ||
436 | fclose(file); | ||
434 | } | 437 | } |
435 | fclose(file); | ||
436 | } | 438 | } |
437 | #endif /* PS_ADDITIONAL_COLUMNS */ | 439 | #endif /* PS_ADDITIONAL_COLUMNS */ |
440 | if (flags & PSSCAN_EXE) { | ||
441 | strcpy(filename_tail, "exe"); | ||
442 | free(sp->exe); | ||
443 | sp->exe = xmalloc_readlink(filename); | ||
444 | } | ||
445 | /* Note: if /proc/PID/cmdline is empty, | ||
446 | * code below "breaks". Therefore it must be | ||
447 | * the last code to parse /proc/PID/xxx data | ||
448 | * (we used to have /proc/PID/exe parsing after it | ||
449 | * and were getting stale sp->exe). | ||
450 | */ | ||
438 | #if 0 /* PSSCAN_CMD is not used */ | 451 | #if 0 /* PSSCAN_CMD is not used */ |
439 | if (flags & (PSSCAN_CMD|PSSCAN_ARGV0)) { | 452 | if (flags & (PSSCAN_CMD|PSSCAN_ARGV0)) { |
440 | free(sp->argv0); | 453 | free(sp->argv0); |
@@ -477,13 +490,9 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) | |||
477 | } | 490 | } |
478 | } | 491 | } |
479 | #endif | 492 | #endif |
480 | if (flags & PSSCAN_EXE) { | ||
481 | strcpy(filename_tail, "exe"); | ||
482 | free(sp->exe); | ||
483 | sp->exe = xmalloc_readlink(filename); | ||
484 | } | ||
485 | break; | 493 | break; |
486 | } | 494 | } /* for (;;) */ |
495 | |||
487 | return sp; | 496 | return sp; |
488 | } | 497 | } |
489 | 498 | ||