ddb ps: Use the pidhash to enumerate processes not in allproc.

Exiting processes that have been removed from allproc but are still
executing are not yet marked PRS_ZOMBIE, so they were not listed (for
example, if a thread panics during exit1()).  To detect these
processes, clear p_list.le_prev to NULL explicitly after removing a
process from the allproc list and check for this sentinel rather than
PRS_ZOMBIE when walking the pidhash.

While here, simplify the pidhash walk to use a single outer loop.

Reviewed by:	kib
Sponsored by:	Netflix
Differential Revision:	https://reviews.freebsd.org/D27824
This commit is contained in:
John Baldwin 2020-12-31 16:00:05 -08:00
parent 68dc94c7d3
commit 47877889f2
2 changed files with 15 additions and 8 deletions

View file

@ -107,7 +107,7 @@ void
db_ps(db_expr_t addr, bool hasaddr, db_expr_t count, char *modif)
{
struct proc *p;
int i, j;
int i;
ps_mode = modif[0] == 'a' ? PRINT_ARGS : PRINT_NONE;
@ -125,14 +125,12 @@ db_ps(db_expr_t addr, bool hasaddr, db_expr_t count, char *modif)
db_ps_proc(p);
/*
* Do zombies.
* Processes such as zombies not in allproc.
*/
for (i = 0; i < pidhashlock + 1 && !db_pager_quit; i++) {
for (j = i; j <= pidhash && !db_pager_quit; j += pidhashlock + 1) {
LIST_FOREACH(p, &pidhashtbl[j], p_hash) {
if (p->p_state == PRS_ZOMBIE)
db_ps_proc(p);
}
for (i = 0; i <= pidhash && !db_pager_quit; i++) {
LIST_FOREACH(p, &pidhashtbl[i], p_hash) {
if (p->p_list.le_prev == NULL)
db_ps_proc(p);
}
}
}

View file

@ -39,6 +39,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include "opt_ktrace.h"
#include <sys/param.h>
@ -436,6 +437,14 @@ exit1(struct thread *td, int rval, int signo)
*/
sx_xlock(&allproc_lock);
LIST_REMOVE(p, p_list);
#ifdef DDB
/*
* Used by ddb's 'ps' command to find this process via the
* pidhash.
*/
p->p_list.le_prev = NULL;
#endif
sx_xunlock(&allproc_lock);
sx_xlock(&proctree_lock);