diff options
author | Jilles Tjoelker <jilles@FreeBSD.org> | 2013-11-17 22:31:23 +0000 |
---|---|---|
committer | Jilles Tjoelker <jilles@FreeBSD.org> | 2013-11-17 22:31:23 +0000 |
commit | b20a9aa92a174e3769baa4defbdabd88d535d568 (patch) | |
tree | 45371901b9ef7392a1ee46ec90518967f3054c20 /sys/kern/kern_sig.c | |
parent | a8eb9360d394b01eb90d467c379b4f488bf394ac (diff) | |
download | src-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.c | 19 |
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(). |