aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_sig.c
diff options
context:
space:
mode:
authorJilles Tjoelker <jilles@FreeBSD.org>2013-11-17 22:31:23 +0000
committerJilles Tjoelker <jilles@FreeBSD.org>2013-11-17 22:31:23 +0000
commitb20a9aa92a174e3769baa4defbdabd88d535d568 (patch)
tree45371901b9ef7392a1ee46ec90518967f3054c20 /sys/kern/kern_sig.c
parenta8eb9360d394b01eb90d467c379b4f488bf394ac (diff)
downloadsrc-b20a9aa92a174e3769baa4defbdabd88d535d568.tar.gz
src-b20a9aa92a174e3769baa4defbdabd88d535d568.zip
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 Reported by: Dmitrijs Ledkovs Tested by: Dmitrijs Ledkovs
Notes
Notes: svn path=/head/; revision=258281
Diffstat (limited to 'sys/kern/kern_sig.c')
-rw-r--r--sys/kern/kern_sig.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 1797ebc7dd43..ea4ac261470e 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().