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
top: document H option -- thanks Tony Ernst
top: terabytes -- thanks Tony Ernst
ps: SCHED_BATCH is B
ps: fix s format (signals) output with thread display
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;
union el *list;
list = malloc (size * sizeof (union el));
list = malloc (size * sizeof *list);
if (list == NULL)
exit (3);
@ -97,7 +97,7 @@ split_list (const char *restrict str, int (*convert)(const char *, union el *))
exit (2);
if (i == size) {
size *= 2;
list = realloc (list, size * sizeof (union el));
list = realloc (list, size * sizeof *list);
if (list == NULL)
exit (3);
}
@ -112,7 +112,7 @@ split_list (const char *restrict str, int (*convert)(const char *, union el *))
} else {
list[0].num = i - 1;
}
return (list);
return list;
}
/* 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';
}
*value = sign * res;
return (1);
return 1;
}
static int
@ -153,10 +153,10 @@ conv_uid (const char *restrict name, union el *restrict e)
if (pwd == NULL) {
fprintf (stderr, "%s: invalid user name: %s\n",
progname, name);
return (0);
return 0;
}
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;
if (strict_atol (name, &e->num))
return (1);
return 1;
grp = getgrnam (name);
if (grp == NULL) {
fprintf (stderr, "%s: invalid group name: %s\n",
progname, name);
return (0);
return 0;
}
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)) {
fprintf (stderr, "%s: invalid process group: %s\n",
progname, name);
return (0);
return 0;
}
if (e->num == 0)
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)) {
fprintf (stderr, "%s: invalid session id: %s\n",
progname, name);
return (0);
return 0;
}
if (e->num == 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)) {
fprintf (stderr, "%s: not a number: %s\n",
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)
{
e->str = strdup (name);
return (1);
return 1;
}
@ -240,7 +240,7 @@ match_numlist (long value, const union el *restrict list)
found = 1;
}
}
return (found);
return found;
}
static int
@ -256,7 +256,7 @@ match_strlist (const char *restrict value, const union el *restrict list)
found = 1;
}
}
return (found);
return found;
}
static void
@ -310,7 +310,7 @@ do_openproc (void)
} else {
ptp = openproc (flags);
}
return (ptp);
return ptp;
}
static regex_t *
@ -346,7 +346,7 @@ do_regcomp (void)
}
static union el *
select_procs (void)
select_procs (int *num)
{
PROCTAB *ptp;
proc_t task;
@ -359,7 +359,7 @@ select_procs (void)
union el *list;
char cmd[4096];
list = malloc (size * sizeof (union el));
list = malloc (size * sizeof *list);
if (list == NULL)
exit (3);
@ -450,14 +450,13 @@ select_procs (void)
if (opt_long) {
char buff[5096]; // FIXME
sprintf (buff, "%d %s", task.XXXID, cmd);
list[++matches].str = strdup (buff);
list[matches++].str = strdup (buff);
} else {
list[++matches].num = task.XXXID;
list[matches++].num = task.XXXID;
}
if (matches == size) {
size *= 2;
list = realloc (list,
size * sizeof (union el));
list = realloc(list, size * sizeof *list);
if (list == NULL)
exit (3);
}
@ -467,8 +466,8 @@ select_procs (void)
}
closeproc (ptp);
list[0].num = matches;
return (list);
*num = matches;
return list;
}
@ -607,13 +606,14 @@ int
main (int argc, char **argv)
{
union el *procs;
int num;
parse_opts (argc, argv);
procs = select_procs ();
procs = select_procs (&num);
if (i_am_pkill) {
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 (errno==ESRCH) continue; // gone now, which is OK
fprintf (stderr, "pkill: %ld - %s\n",
@ -625,5 +625,5 @@ main (int argc, char **argv)
else
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)
#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;
///////////////////////////////////////////////////////////////////////////
@ -71,7 +82,6 @@ typedef struct status_table_struct {
// must be padded out to 64 entries, maybe 128 in the future.
static void status2proc(char *S, proc_t *restrict P, int is_proc){
char ShdPnd[16] = "";
long Threads = 0;
long Tgid = 0;
long Pid = 0;
@ -147,6 +157,7 @@ ENTER(0x220);
P->vm_exe = 0;
P->vm_lib = 0;
P->nlwp = 0;
P->signal[0] = '\0'; // so we can detect it as missing for very old kernels
goto base;
@ -195,9 +206,10 @@ ENTER(0x220);
S--; // put back the '\n' or '\0'
continue;
}
#ifdef SIGNAL_STRING
case_ShdPnd:
memcpy(ShdPnd, S, 16);
// we know it to be 16 char, so no '\0' needed
memcpy(P->signal, S, 16);
P->signal[16] = '\0';
continue;
case_SigBlk:
memcpy(P->blocked, S, 16);
@ -212,9 +224,26 @@ ENTER(0x220);
P->sigignore[16] = '\0';
continue;
case_SigPnd:
memcpy(P->signal, S, 16);
P->signal[16] = '\0';
memcpy(P->_sigpnd, S, 16);
P->_sigpnd[16] = '\0';
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:
P->state = *S;
continue;
@ -265,11 +294,25 @@ ENTER(0x220);
continue;
}
#if 0
// recent kernels supply per-tgid pending signals
if(is_proc && *ShdPnd){
memcpy(P->signal, ShdPnd, 16);
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"
// 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 */
// 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(PT->did_fake) goto out;
PT->did_fake=1;
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;
}

View File

@ -58,17 +58,19 @@ typedef struct proc_t {
#ifdef SIGNAL_STRING
char
// 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
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
long long
// 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
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
unsigned KLONG
start_code, // stat address of beginning of code segment