svn commit: r258281 - head/sys/kern

Jilles Tjoelker jilles at FreeBSD.org
Sun Nov 17 22:31:24 UTC 2013


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().


More information about the svn-src-all mailing list