We should not return ECHILD when debugging a child and the parent does a
"wait4(-1, ..., WNOHANG, ...)". Instead wait(2) should behave as if the child does not wish to report status at this time. Reviewed by: jhb
This commit is contained in:
parent
0b41fa9638
commit
f797e31a8d
@ -701,8 +701,9 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options,
|
||||
*/
|
||||
if (p->p_oppid && (t = pfind(p->p_oppid)) != NULL) {
|
||||
PROC_LOCK(p);
|
||||
p->p_oppid = 0;
|
||||
proc_reparent(p, t);
|
||||
p->p_pptr->p_dbg_child--;
|
||||
p->p_oppid = 0;
|
||||
PROC_UNLOCK(p);
|
||||
pksignal(t, SIGCHLD, p->p_ksi);
|
||||
wakeup(t);
|
||||
@ -794,7 +795,8 @@ kern_wait(struct thread *td, pid_t pid, int *status, int options,
|
||||
pid = -q->p_pgid;
|
||||
PROC_UNLOCK(q);
|
||||
}
|
||||
if (options &~ (WUNTRACED|WNOHANG|WCONTINUED|WNOWAIT|WLINUXCLONE))
|
||||
/* If we don't know the option, just return. */
|
||||
if (options & ~(WUNTRACED|WNOHANG|WCONTINUED|WNOWAIT|WLINUXCLONE))
|
||||
return (EINVAL);
|
||||
loop:
|
||||
if (q->p_flag & P_STATCHILD) {
|
||||
@ -873,7 +875,10 @@ loop:
|
||||
}
|
||||
if (nfound == 0) {
|
||||
sx_xunlock(&proctree_lock);
|
||||
return (ECHILD);
|
||||
if (td->td_proc->p_dbg_child)
|
||||
return (0);
|
||||
else
|
||||
return (ECHILD);
|
||||
}
|
||||
if (options & WNOHANG) {
|
||||
sx_xunlock(&proctree_lock);
|
||||
|
@ -831,8 +831,11 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
/* security check done above */
|
||||
p->p_flag |= P_TRACED;
|
||||
p->p_oppid = p->p_pptr->p_pid;
|
||||
if (p->p_pptr != td->td_proc)
|
||||
if (p->p_pptr != td->td_proc) {
|
||||
/* Remember that a child is being debugged(traced). */
|
||||
p->p_pptr->p_dbg_child++;
|
||||
proc_reparent(p, td->td_proc);
|
||||
}
|
||||
data = SIGSTOP;
|
||||
goto sendsig; /* in PT_CONTINUE below */
|
||||
|
||||
@ -919,11 +922,12 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
PROC_UNLOCK(pp);
|
||||
PROC_LOCK(p);
|
||||
proc_reparent(p, pp);
|
||||
p->p_pptr->p_dbg_child--;
|
||||
if (pp == initproc)
|
||||
p->p_sigparent = SIGCHLD;
|
||||
}
|
||||
p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK);
|
||||
p->p_oppid = 0;
|
||||
p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK);
|
||||
|
||||
/* should we send SIGCHLD? */
|
||||
/* childproc_continued(p); */
|
||||
|
@ -503,6 +503,8 @@ struct proc {
|
||||
/* The following fields are all zeroed upon creation in fork. */
|
||||
#define p_startzero p_oppid
|
||||
pid_t p_oppid; /* (c + e) Save ppid in ptrace. XXX */
|
||||
int p_dbg_child; /* (c + e) # of debugged children in
|
||||
ptrace. */
|
||||
struct vmspace *p_vmspace; /* (b) Address space. */
|
||||
u_int p_swtick; /* (c) Tick when swapped in or out. */
|
||||
struct itimerval p_realtimer; /* (c) Alarm timer. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user