Author: jilles
Date: Sun Nov 17 22:31:23 2013
New Revision: 258281
URL: http://svnweb.freebsd.org/changeset/base/258281

Log:
  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

Modified:
  head/sys/kern/kern_exit.c
  head/sys/kern/kern_sig.c

Modified: head/sys/kern/kern_exit.c
==============================================================================
--- head/sys/kern/kern_exit.c   Sun Nov 17 22:24:34 2013        (r258280)
+++ head/sys/kern/kern_exit.c   Sun Nov 17 22:31:23 2013        (r258281)
@@ -974,16 +974,19 @@ proc_to_reap(struct thread *td, struct p
                 *  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

Modified: head/sys/kern/kern_sig.c
==============================================================================
--- head/sys/kern/kern_sig.c    Sun Nov 17 22:24:34 2013        (r258280)
+++ head/sys/kern/kern_sig.c    Sun Nov 17 22:31:23 2013        (r258281)
@@ -2959,7 +2959,7 @@ sigparent(struct proc *p, int reason, in
 }
 
 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 r
        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 r
 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().
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to