summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2014-01-01 20:22:29 +0000
committerjilles <jilles@FreeBSD.org>2014-01-01 20:22:29 +0000
commitf948fdf9e9c8f3e33fa0b06ffba7d6fccc436694 (patch)
tree444e613ddde85e05d25deb24f27b98693ebbb2ba
parente876d4736cec7a72c621f94d97df99a81f04693a (diff)
downloadFreeBSD-src-f948fdf9e9c8f3e33fa0b06ffba7d6fccc436694.zip
FreeBSD-src-f948fdf9e9c8f3e33fa0b06ffba7d6fccc436694.tar.gz
MFC r258281: Fix siginfo_t.si_status for wait6/waitid/SIGCHLD.
Per POSIX, si_status should contain the value passed to exit() for si_code==CLD_EXITED and the signal number for other si_code. This was incorrect for CLD_EXITED and CLD_DUMPED. This is still not fully POSIX-compliant (Austin group issue #594 says that the full value passed to exit() shall be returned via si_status, not just the low 8 bits) but is sufficient for a si_status-related test in libnih (upstart, Debian/kFreeBSD). PR: kern/184002
-rw-r--r--sys/kern/kern_exit.c11
-rw-r--r--sys/kern/kern_sig.c19
2 files changed, 18 insertions, 12 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index f0be10e..1a68bf5 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -974,16 +974,19 @@ proc_to_reap(struct thread *td, struct proc *p, idtype_t idtype, id_t id,
* This is still a rough estimate. We will fix the
* cases TRAPPED, STOPPED, and CONTINUED later.
*/
- if (WCOREDUMP(p->p_xstat))
+ if (WCOREDUMP(p->p_xstat)) {
siginfo->si_code = CLD_DUMPED;
- else if (WIFSIGNALED(p->p_xstat))
+ siginfo->si_status = WTERMSIG(p->p_xstat);
+ } else if (WIFSIGNALED(p->p_xstat)) {
siginfo->si_code = CLD_KILLED;
- else
+ siginfo->si_status = WTERMSIG(p->p_xstat);
+ } else {
siginfo->si_code = CLD_EXITED;
+ siginfo->si_status = WEXITSTATUS(p->p_xstat);
+ }
siginfo->si_pid = p->p_pid;
siginfo->si_uid = p->p_ucred->cr_uid;
- siginfo->si_status = p->p_xstat;
/*
* The si_addr field would be useful additional
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 1797ebc..ea4ac26 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -2959,7 +2959,7 @@ sigparent(struct proc *p, int reason, int status)
}
static void
-childproc_jobstate(struct proc *p, int reason, int status)
+childproc_jobstate(struct proc *p, int reason, int sig)
{
struct sigacts *ps;
@@ -2979,7 +2979,7 @@ childproc_jobstate(struct proc *p, int reason, int status)
mtx_lock(&ps->ps_mtx);
if ((ps->ps_flag & PS_NOCLDSTOP) == 0) {
mtx_unlock(&ps->ps_mtx);
- sigparent(p, reason, status);
+ sigparent(p, reason, sig);
} else
mtx_unlock(&ps->ps_mtx);
}
@@ -2987,6 +2987,7 @@ childproc_jobstate(struct proc *p, int reason, int status)
void
childproc_stopped(struct proc *p, int reason)
{
+ /* p_xstat is a plain signal number, not a full wait() status here. */
childproc_jobstate(p, reason, p->p_xstat);
}
@@ -3000,13 +3001,15 @@ void
childproc_exited(struct proc *p)
{
int reason;
- int status = p->p_xstat; /* convert to int */
+ int xstat = p->p_xstat; /* convert to int */
+ int status;
- reason = CLD_EXITED;
- if (WCOREDUMP(status))
- reason = CLD_DUMPED;
- else if (WIFSIGNALED(status))
- reason = CLD_KILLED;
+ if (WCOREDUMP(xstat))
+ reason = CLD_DUMPED, status = WTERMSIG(xstat);
+ else if (WIFSIGNALED(xstat))
+ reason = CLD_KILLED, status = WTERMSIG(xstat);
+ else
+ reason = CLD_EXITED, status = WEXITSTATUS(xstat);
/*
* XXX avoid calling wakeup(p->p_pptr), the work is
* done in exit1().
OpenPOWER on IntegriCloud