fix "ps sm" bug involving 1-thread-proc optimization

This commit is contained in:
albert 2006-06-17 04:14:57 +00:00
parent 20fba946af
commit 5c591b836f
4 changed files with 93 additions and 40 deletions

2
NEWS
View File

@ -1,7 +1,9 @@
procps-3.2.6 --> procps-3.2.7 procps-3.2.6 --> procps-3.2.7
top: document H option -- thanks Tony Ernst top: document H option -- thanks Tony Ernst
top: terabytes -- thanks Tony Ernst top: terabytes -- thanks Tony Ernst
ps: SCHED_BATCH is B ps: SCHED_BATCH is B
ps: fix s format (signals) output with thread display
procps-3.2.5 --> procps-3.2.6 procps-3.2.5 --> procps-3.2.6

60
pgrep.c
View File

@ -83,7 +83,7 @@ split_list (const char *restrict str, int (*convert)(const char *, union el *))
int i = 1, size = 32; int i = 1, size = 32;
union el *list; union el *list;
list = malloc (size * sizeof (union el)); list = malloc (size * sizeof *list);
if (list == NULL) if (list == NULL)
exit (3); exit (3);
@ -97,7 +97,7 @@ split_list (const char *restrict str, int (*convert)(const char *, union el *))
exit (2); exit (2);
if (i == size) { if (i == size) {
size *= 2; size *= 2;
list = realloc (list, size * sizeof (union el)); list = realloc (list, size * sizeof *list);
if (list == NULL) if (list == NULL)
exit (3); exit (3);
} }
@ -112,7 +112,7 @@ split_list (const char *restrict str, int (*convert)(const char *, union el *))
} else { } else {
list[0].num = i - 1; list[0].num = i - 1;
} }
return (list); return list;
} }
/* strict_atol returns a Boolean: TRUE if the input string contains a /* strict_atol returns a Boolean: TRUE if the input string contains a
@ -138,7 +138,7 @@ strict_atol (const char *restrict str, long *restrict value)
res += *str - '0'; res += *str - '0';
} }
*value = sign * res; *value = sign * res;
return (1); return 1;
} }
static int static int
@ -153,10 +153,10 @@ conv_uid (const char *restrict name, union el *restrict e)
if (pwd == NULL) { if (pwd == NULL) {
fprintf (stderr, "%s: invalid user name: %s\n", fprintf (stderr, "%s: invalid user name: %s\n",
progname, name); progname, name);
return (0); return 0;
} }
e->num = pwd->pw_uid; e->num = pwd->pw_uid;
return (1); return 1;
} }
@ -166,16 +166,16 @@ conv_gid (const char *restrict name, union el *restrict e)
struct group *grp; struct group *grp;
if (strict_atol (name, &e->num)) if (strict_atol (name, &e->num))
return (1); return 1;
grp = getgrnam (name); grp = getgrnam (name);
if (grp == NULL) { if (grp == NULL) {
fprintf (stderr, "%s: invalid group name: %s\n", fprintf (stderr, "%s: invalid group name: %s\n",
progname, name); progname, name);
return (0); return 0;
} }
e->num = grp->gr_gid; e->num = grp->gr_gid;
return (1); return 1;
} }
@ -185,11 +185,11 @@ conv_pgrp (const char *restrict name, union el *restrict e)
if (! strict_atol (name, &e->num)) { if (! strict_atol (name, &e->num)) {
fprintf (stderr, "%s: invalid process group: %s\n", fprintf (stderr, "%s: invalid process group: %s\n",
progname, name); progname, name);
return (0); return 0;
} }
if (e->num == 0) if (e->num == 0)
e->num = getpgrp (); e->num = getpgrp ();
return (1); return 1;
} }
@ -199,11 +199,11 @@ conv_sid (const char *restrict name, union el *restrict e)
if (! strict_atol (name, &e->num)) { if (! strict_atol (name, &e->num)) {
fprintf (stderr, "%s: invalid session id: %s\n", fprintf (stderr, "%s: invalid session id: %s\n",
progname, name); progname, name);
return (0); return 0;
} }
if (e->num == 0) if (e->num == 0)
e->num = getsid (0); e->num = getsid (0);
return (1); return 1;
} }
@ -213,9 +213,9 @@ conv_num (const char *restrict name, union el *restrict e)
if (! strict_atol (name, &e->num)) { if (! strict_atol (name, &e->num)) {
fprintf (stderr, "%s: not a number: %s\n", fprintf (stderr, "%s: not a number: %s\n",
progname, name); progname, name);
return (0); return 0;
} }
return (1); return 1;
} }
@ -223,7 +223,7 @@ static int
conv_str (const char *restrict name, union el *restrict e) conv_str (const char *restrict name, union el *restrict e)
{ {
e->str = strdup (name); e->str = strdup (name);
return (1); return 1;
} }
@ -240,7 +240,7 @@ match_numlist (long value, const union el *restrict list)
found = 1; found = 1;
} }
} }
return (found); return found;
} }
static int static int
@ -256,7 +256,7 @@ match_strlist (const char *restrict value, const union el *restrict list)
found = 1; found = 1;
} }
} }
return (found); return found;
} }
static void static void
@ -310,7 +310,7 @@ do_openproc (void)
} else { } else {
ptp = openproc (flags); ptp = openproc (flags);
} }
return (ptp); return ptp;
} }
static regex_t * static regex_t *
@ -346,7 +346,7 @@ do_regcomp (void)
} }
static union el * static union el *
select_procs (void) select_procs (int *num)
{ {
PROCTAB *ptp; PROCTAB *ptp;
proc_t task; proc_t task;
@ -359,7 +359,7 @@ select_procs (void)
union el *list; union el *list;
char cmd[4096]; char cmd[4096];
list = malloc (size * sizeof (union el)); list = malloc (size * sizeof *list);
if (list == NULL) if (list == NULL)
exit (3); exit (3);
@ -450,14 +450,13 @@ select_procs (void)
if (opt_long) { if (opt_long) {
char buff[5096]; // FIXME char buff[5096]; // FIXME
sprintf (buff, "%d %s", task.XXXID, cmd); sprintf (buff, "%d %s", task.XXXID, cmd);
list[++matches].str = strdup (buff); list[matches++].str = strdup (buff);
} else { } else {
list[++matches].num = task.XXXID; list[matches++].num = task.XXXID;
} }
if (matches == size) { if (matches == size) {
size *= 2; size *= 2;
list = realloc (list, list = realloc(list, size * sizeof *list);
size * sizeof (union el));
if (list == NULL) if (list == NULL)
exit (3); exit (3);
} }
@ -467,8 +466,8 @@ select_procs (void)
} }
closeproc (ptp); closeproc (ptp);
list[0].num = matches; *num = matches;
return (list); return list;
} }
@ -607,13 +606,14 @@ int
main (int argc, char **argv) main (int argc, char **argv)
{ {
union el *procs; union el *procs;
int num;
parse_opts (argc, argv); parse_opts (argc, argv);
procs = select_procs (); procs = select_procs (&num);
if (i_am_pkill) { if (i_am_pkill) {
int i; int i;
for (i = 1; i <= procs[0].num; i++) { for (i = 0; i < num; i++) {
if (kill (procs[i].num, opt_signal) != -1) continue; if (kill (procs[i].num, opt_signal) != -1) continue;
if (errno==ESRCH) continue; // gone now, which is OK if (errno==ESRCH) continue; // gone now, which is OK
fprintf (stderr, "pkill: %ld - %s\n", fprintf (stderr, "pkill: %ld - %s\n",
@ -625,5 +625,5 @@ main (int argc, char **argv)
else else
output_numlist (procs); output_numlist (procs);
} }
return ((procs[0].num) == 0 ? 1 : 0); return !num;
} }

View File

@ -37,6 +37,17 @@ extern void __cyg_profile_func_enter(void*,void*);
#define LEAVE(x) #define LEAVE(x)
#endif #endif
// convert hex string to unsigned long long
static unsigned long long unhex(const char *restrict cp){
unsigned long long ull = 0;
for(;;){
char c = *cp++;
if(unlikely(c<0x30)) break;
ull = (ull<<4) | (c - (c>0x57) ? 0x57 : 0x30) ;
}
return ull;
}
static int task_dir_missing; static int task_dir_missing;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -71,7 +82,6 @@ typedef struct status_table_struct {
// must be padded out to 64 entries, maybe 128 in the future. // must be padded out to 64 entries, maybe 128 in the future.
static void status2proc(char *S, proc_t *restrict P, int is_proc){ static void status2proc(char *S, proc_t *restrict P, int is_proc){
char ShdPnd[16] = "";
long Threads = 0; long Threads = 0;
long Tgid = 0; long Tgid = 0;
long Pid = 0; long Pid = 0;
@ -147,6 +157,7 @@ ENTER(0x220);
P->vm_exe = 0; P->vm_exe = 0;
P->vm_lib = 0; P->vm_lib = 0;
P->nlwp = 0; P->nlwp = 0;
P->signal[0] = '\0'; // so we can detect it as missing for very old kernels
goto base; goto base;
@ -195,9 +206,10 @@ ENTER(0x220);
S--; // put back the '\n' or '\0' S--; // put back the '\n' or '\0'
continue; continue;
} }
#ifdef SIGNAL_STRING
case_ShdPnd: case_ShdPnd:
memcpy(ShdPnd, S, 16); memcpy(P->signal, S, 16);
// we know it to be 16 char, so no '\0' needed P->signal[16] = '\0';
continue; continue;
case_SigBlk: case_SigBlk:
memcpy(P->blocked, S, 16); memcpy(P->blocked, S, 16);
@ -212,9 +224,26 @@ ENTER(0x220);
P->sigignore[16] = '\0'; P->sigignore[16] = '\0';
continue; continue;
case_SigPnd: case_SigPnd:
memcpy(P->signal, S, 16); memcpy(P->_sigpnd, S, 16);
P->signal[16] = '\0'; P->_sigpnd[16] = '\0';
continue; continue;
#else
case_ShdPnd:
P->signal = unhex(S);
continue;
case_SigBlk:
P->blocked = unhex(S);
continue;
case_SigCgt:
P->sigcatch = unhex(S);
continue;
case_SigIgn:
P->sigignore = unhex(S);
continue;
case_SigPnd:
P->_sigpnd = unhex(S);
continue;
#endif
case_State: case_State:
P->state = *S; P->state = *S;
continue; continue;
@ -265,11 +294,25 @@ ENTER(0x220);
continue; continue;
} }
#if 0
// recent kernels supply per-tgid pending signals // recent kernels supply per-tgid pending signals
if(is_proc && *ShdPnd){ if(is_proc && *ShdPnd){
memcpy(P->signal, ShdPnd, 16); memcpy(P->signal, ShdPnd, 16);
P->signal[16] = '\0'; P->signal[16] = '\0';
} }
#endif
// recent kernels supply per-tgid pending signals
#ifdef SIGNAL_STRING
if(!is_proc || !P->signal[0]){
memcpy(P->signal, P->_sigpnd, 16);
P->signal[16] = '\0';
}
#else
if(!is_proc || !have_process_pending){
P->signal = P->_sigpnd;
}
#endif
// Linux 2.4.13-pre1 to max 2.4.xx have a useless "Tgid" // Linux 2.4.13-pre1 to max 2.4.xx have a useless "Tgid"
// that is not initialized for built-in kernel tasks. // that is not initialized for built-in kernel tasks.
@ -764,11 +807,17 @@ proc_t* readtask(PROCTAB *restrict const PT, const proc_t *restrict const p, pro
if(!t) t = xcalloc(t, sizeof *t); /* passed buf or alloced mem */ if(!t) t = xcalloc(t, sizeof *t); /* passed buf or alloced mem */
// 1. got to fake a thread for old kernels // 1. got to fake a thread for old kernels
// 2. for single-threaded processes, this is faster // 2. for single-threaded processes, this is faster (but must patch up stuff that differs!)
if(task_dir_missing || p->nlwp < 2){ if(task_dir_missing || p->nlwp < 2){
if(PT->did_fake) goto out; if(PT->did_fake) goto out;
PT->did_fake=1; PT->did_fake=1;
memcpy(t,p,sizeof(proc_t)); memcpy(t,p,sizeof(proc_t));
// use the per-task pending, not per-tgid pending
#ifdef SIGNAL_STRING
memcpy(&t->signal, &t->_sigpnd, sizeof t->signal);
#else
t->signal = t->_sigpnd;
#endif
return t; return t;
} }

View File

@ -58,17 +58,19 @@ typedef struct proc_t {
#ifdef SIGNAL_STRING #ifdef SIGNAL_STRING
char char
// Linux 2.1.7x and up have 64 signals. Allow 64, plus '\0' and padding. // Linux 2.1.7x and up have 64 signals. Allow 64, plus '\0' and padding.
signal[18], // status mask of pending signals signal[18], // status mask of pending signals, per-task for readtask() but per-proc for readproc()
blocked[18], // status mask of blocked signals blocked[18], // status mask of blocked signals
sigignore[18], // status mask of ignored signals sigignore[18], // status mask of ignored signals
sigcatch[18]; // status mask of caught signals sigcatch[18], // status mask of caught signals
_sigpnd[18]; // status mask of PER TASK pending signals
#else #else
long long long long
// Linux 2.1.7x and up have 64 signals. // Linux 2.1.7x and up have 64 signals.
signal, // status mask of pending signals signal, // status mask of pending signals, per-task for readtask() but per-proc for readproc()
blocked, // status mask of blocked signals blocked, // status mask of blocked signals
sigignore, // status mask of ignored signals sigignore, // status mask of ignored signals
sigcatch; // status mask of caught signals sigcatch, // status mask of caught signals
_sigpnd; // status mask of PER TASK pending signals
#endif #endif
unsigned KLONG unsigned KLONG
start_code, // stat address of beginning of code segment start_code, // stat address of beginning of code segment