aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-09-22 23:06:07 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-09-22 23:06:07 +0200
commited4ff0e8cbe8b330ecc9c51d0c5ff2ad1647ad5d (patch)
tree07a10f1bfdee005231cd17a230d9e4fbf5857483 /libbb
parent200d522fb85c24dd1ed36e5fcc29c1140b8b428b (diff)
downloadbusybox-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.c133
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