MFC r269656:

Implement and use proc_realparent(9).

MFC r270024 (by markj):
Correct the order of arguments passed to LIST_INSERT_AFTER().

For merge, the p_treeflag member of struct proc was moved to the end
of the structure, to keep KBI intact.
This commit is contained in:
kib 2014-08-21 10:46:19 +00:00
parent 9ac8060e57
commit afeea342d6
5 changed files with 59 additions and 23 deletions

View File

@ -29,7 +29,7 @@
.\" @(#)ps.1 8.3 (Berkeley) 4/18/94
.\" $FreeBSD$
.\"
.Dd June 6, 2014
.Dd August 7, 2014
.Dt PS 1
.Os
.Sh NAME
@ -332,7 +332,6 @@ the include file
.It Dv "P_SINGLE_BOUNDARY" Ta No "0x400000" Ta "Threads should suspend at user boundary"
.It Dv "P_HWPMC" Ta No "0x800000" Ta "Process is using HWPMCs"
.It Dv "P_JAILED" Ta No "0x1000000" Ta "Process is in jail"
.It Dv "P_ORPHAN" Ta No "0x2000000" Ta "Orphaned by original parent, reparented to debugger"
.It Dv "P_INEXEC" Ta No "0x4000000" Ta "Process is in execve()"
.It Dv "P_STATCHILD" Ta No "0x8000000" Ta "Child process stopped or exited"
.It Dv "P_INMEM" Ta No "0x10000000" Ta "Loaded into memory"

View File

@ -99,16 +99,44 @@ SDT_PROBE_DEFINE1(proc, kernel, , exit, "int");
/* Hook for NFS teardown procedure. */
void (*nlminfo_release_p)(struct proc *p);
struct proc *
proc_realparent(struct proc *child)
{
struct proc *p, *parent;
sx_assert(&proctree_lock, SX_LOCKED);
if ((child->p_treeflag & P_TREE_ORPHANED) == 0) {
return (child->p_pptr->p_pid == child->p_oppid ?
child->p_pptr : initproc);
}
for (p = child; (p->p_treeflag & P_TREE_FIRST_ORPHAN) == 0;) {
/* Cannot use LIST_PREV(), since the list head is not known. */
p = __containerof(p->p_orphan.le_prev, struct proc,
p_orphan.le_next);
KASSERT((p->p_treeflag & P_TREE_ORPHANED) != 0,
("missing P_ORPHAN %p", p));
}
parent = __containerof(p->p_orphan.le_prev, struct proc,
p_orphans.lh_first);
return (parent);
}
static void
clear_orphan(struct proc *p)
{
struct proc *p1;
PROC_LOCK_ASSERT(p, MA_OWNED);
if (p->p_flag & P_ORPHAN) {
LIST_REMOVE(p, p_orphan);
p->p_flag &= ~P_ORPHAN;
sx_assert(&proctree_lock, SA_XLOCKED);
if ((p->p_treeflag & P_TREE_ORPHANED) == 0)
return;
if ((p->p_treeflag & P_TREE_FIRST_ORPHAN) != 0) {
p1 = LIST_NEXT(p, p_orphan);
if (p1 != NULL)
p1->p_treeflag |= P_TREE_FIRST_ORPHAN;
p->p_treeflag &= ~P_TREE_FIRST_ORPHAN;
}
LIST_REMOVE(p, p_orphan);
p->p_treeflag &= ~P_TREE_ORPHANED;
}
/*
@ -778,7 +806,9 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options)
* If we got the child via a ptrace 'attach', we need to give it back
* to the old parent.
*/
if (p->p_oppid && (t = pfind(p->p_oppid)) != NULL) {
if (p->p_oppid != 0) {
t = proc_realparent(p);
PROC_LOCK(t);
PROC_LOCK(p);
proc_reparent(p, t);
p->p_oppid = 0;
@ -1251,8 +1281,15 @@ proc_reparent(struct proc *child, struct proc *parent)
clear_orphan(child);
if (child->p_flag & P_TRACED) {
LIST_INSERT_HEAD(&child->p_pptr->p_orphans, child, p_orphan);
child->p_flag |= P_ORPHAN;
if (LIST_EMPTY(&child->p_pptr->p_orphans)) {
child->p_treeflag |= P_TREE_FIRST_ORPHAN;
LIST_INSERT_HEAD(&child->p_pptr->p_orphans, child,
p_orphan);
} else {
LIST_INSERT_AFTER(LIST_FIRST(&child->p_pptr->p_orphans),
child, p_orphan);
}
child->p_treeflag |= P_TREE_ORPHANED;
}
child->p_pptr = parent;

View File

@ -264,14 +264,15 @@ proc_fini(void *mem, int size)
* Is p an inferior of the current process?
*/
int
inferior(p)
register struct proc *p;
inferior(struct proc *p)
{
sx_assert(&proctree_lock, SX_LOCKED);
for (; p != curproc; p = p->p_pptr)
PROC_LOCK_ASSERT(p, MA_OWNED);
for (; p != curproc; p = proc_realparent(p)) {
if (p->p_pid == 0)
return (0);
}
return (1);
}

View File

@ -917,19 +917,11 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
case PT_DETACH:
/* reset process parent */
if (p->p_oppid != p->p_pptr->p_pid) {
struct proc *pp;
PROC_LOCK(p->p_pptr);
sigqueue_take(p->p_ksi);
PROC_UNLOCK(p->p_pptr);
PROC_UNLOCK(p);
pp = pfind(p->p_oppid);
if (pp == NULL)
pp = initproc;
else
PROC_UNLOCK(pp);
PROC_LOCK(p);
pp = proc_realparent(p);
proc_reparent(p, pp);
if (pp == initproc)
p->p_sigparent = SIGCHLD;

View File

@ -591,6 +591,7 @@ struct proc {
*/
LIST_ENTRY(proc) p_orphan; /* (e) List of orphan processes. */
LIST_HEAD(, proc) p_orphans; /* (e) Pointer to list of orphans. */
u_int p_treeflag; /* (e) P_TREE flags */
};
#define p_session p_pgrp->pg_session
@ -628,7 +629,7 @@ struct proc {
#define P_SINGLE_BOUNDARY 0x400000 /* Threads should suspend at user boundary. */
#define P_HWPMC 0x800000 /* Process is using HWPMCs */
#define P_JAILED 0x1000000 /* Process is in jail. */
#define P_ORPHAN 0x2000000 /* Orphaned. */
#define P_UNUSED1 0x2000000
#define P_INEXEC 0x4000000 /* Process is in execve(). */
#define P_STATCHILD 0x8000000 /* Child process stopped or exited. */
#define P_INMEM 0x10000000 /* Loaded into memory. */
@ -643,6 +644,11 @@ struct proc {
/* These flags are kept in p_flag2. */
#define P2_INHERIT_PROTECTED 0x00000001 /* New children get P_PROTECTED. */
/* Flags protected by proctree_lock, kept in p_treeflags. */
#define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */
#define P_TREE_FIRST_ORPHAN 0x00000002 /* First element of orphan
list */
/*
* These were process status values (p_stat), now they are only used in
* legacy conversion code.
@ -883,6 +889,7 @@ int proc_getenvv(struct thread *td, struct proc *p, struct sbuf *sb);
void procinit(void);
void proc_linkup0(struct proc *p, struct thread *td);
void proc_linkup(struct proc *p, struct thread *td);
struct proc *proc_realparent(struct proc *child);
void proc_reap(struct thread *td, struct proc *p, int *status, int options);
void proc_reparent(struct proc *child, struct proc *newparent);
struct pstats *pstats_alloc(void);