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:
David E. O'Brien 2011-06-14 17:09:30 +00:00
parent 9acd91270f
commit f528c3fdbc
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=223088
3 changed files with 16 additions and 5 deletions

View File

@ -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 @@ kern_wait(struct thread *td, pid_t pid, int *status, int options,
}
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);

View File

@ -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); */

View File

@ -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. */