fix "ps sm" bug involving 1-thread-proc optimization
This commit is contained in:
parent
20fba946af
commit
5c591b836f
2
NEWS
2
NEWS
@ -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
60
pgrep.c
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user