From nobody@FreeBSD.org  Fri Nov 15 15:28:12 2013
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115])
	(using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by hub.freebsd.org (Postfix) with ESMTPS id E4A50FE7
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 15 Nov 2013 15:28:12 +0000 (UTC)
Received: from oldred.freebsd.org (oldred.freebsd.org [8.8.178.121])
	(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by mx1.freebsd.org (Postfix) with ESMTPS id BA2E220B1
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 15 Nov 2013 15:28:12 +0000 (UTC)
Received: from oldred.freebsd.org ([127.0.1.6])
	by oldred.freebsd.org (8.14.5/8.14.7) with ESMTP id rAFFSCnc079940
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 15 Nov 2013 15:28:12 GMT
	(envelope-from nobody@oldred.freebsd.org)
Received: (from nobody@localhost)
	by oldred.freebsd.org (8.14.5/8.14.5/Submit) id rAFFSCQ2079936;
	Fri, 15 Nov 2013 15:28:12 GMT
	(envelope-from nobody)
Message-Id: <201311151528.rAFFSCQ2079936@oldred.freebsd.org>
Date: Fri, 15 Nov 2013 15:28:12 GMT
From: Dmitrijs Ledkovs <xnox@debian.org>
To: freebsd-gnats-submit@FreeBSD.org
Subject: wait6 / waitid returns wrong value in siginfo.si_status
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         184002
>Category:       kern
>Synopsis:       wait6/waitid/SIGCHLD return wrong siginfo.si_status
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    jilles
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Nov 15 15:30:00 UTC 2013
>Closed-Date:    Fri Jan 03 14:32:39 UTC 2014
>Last-Modified:  Fri Jan  3 14:40:00 UTC 2014
>Originator:     Dmitrijs Ledkovs
>Release:        9.2, 10
>Organization:
Debian
>Environment:
GNU/kFreeBSD kfree 10.0-0-amd64 #0 Fri Aug  2 21:27:23 CEST 2013 x86_64 amd64 QEMU Virtual CPU version 1.6.1 GNU/kFreeBSD
>Description:
As per http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html

siginfo_t.si_status is "Exit value or signal."

The waitid call is suppose to fill in siginfo_t structure if one was passed to the function http://pubs.opengroup.org/onlinepubs/9699919799/functions/waitid.html

Instead at the moment the returned siginfo_t.si_status of FreeBSD is same on as &status returned by waitpid() call. I.E. value which hasn't been extraced with WEXITSTATUS() 
>How-To-Repeat:
The below program should not assert.

#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <assert.h>

int main() {

  siginfo_t siginfo;
  pid_t pid = -1;

  pid = fork ();
  if (pid > 0) {
    waitid (P_PID, pid, &siginfo, WEXITED | WNOWAIT);
    assert (siginfo.si_code == CLD_EXITED);
    assert (siginfo.si_status == 123);
  } else if (pid == 0) {
    exit (123);
  }

}
>Fix:
Untested patch against kfreebsd-source-10.0/sys/kern/kern_exit.c

--- kern_exit.c.orig	2013-11-15 15:23:25.000000000 +0000
+++ kern_exit.c	2013-11-15 15:26:26.000000000 +0000
@@ -975,16 +975,18 @@
 		 *  cases TRAPPED, STOPPED, and CONTINUED later.
 		 */
 		if (WCOREDUMP(p->p_xstat))
 			siginfo->si_code = CLD_DUMPED;
-		else if (WIFSIGNALED(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
 		 * detail, but apparently the PC value may be lost


>Release-Note:
>Audit-Trail:

From: Dmitrijs Ledkovs <dmitrij.ledkov@surgut.co.uk>
To: bug-followup@FreeBSD.org, xnox@debian.org
Cc:  
Subject: Re: misc/184002: wait6 / waitid returns wrong value in siginfo.si_status
Date: Fri, 15 Nov 2013 21:24:14 +0000

 Given that http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/181439 is
 still not fixed, the test case may also require
 
 #include <signal.h>
 
 Including signal.h is not required in Posix, linux/glibc, FreeBSD/glibc.
 Please consider fixing
 http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/181439 as well, to
 make waitid usage the same
 on all POSIX platforms that implement waitid.
 
 Regards,
 
 Dmitrijs.
Responsible-Changed-From-To: freebsd-bugs->jilles 
Responsible-Changed-By: jilles 
Responsible-Changed-When: Sat Nov 16 11:40:49 UTC 2013 
Responsible-Changed-Why:  
I'm handling this. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=184002 

From: Jilles Tjoelker <jilles@stack.nl>
To: bug-followup@FreeBSD.org, xnox@debian.org
Cc:  
Subject: Re: kern/184002: wait6/waitid/SIGCHLD return wrong siginfo.si_status
Date: Sat, 16 Nov 2013 12:57:11 +0100

 In PR kern/184002, you wrote:
 > As per
 > http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html
 
 > siginfo_t.si_status is "Exit value or signal."
 
 > The waitid call is suppose to fill in siginfo_t structure if one was
 > passed to the function
 > http://pubs.opengroup.org/onlinepubs/9699919799/functions/waitid.html
 
 > Instead at the moment the returned siginfo_t.si_status of FreeBSD is
 > same on as &status returned by waitpid() call. I.E. value which hasn't
 > been extraced with WEXITSTATUS()
 
 I have created and tested a patch for this issue. It is a bit trickier
 than it seems because p_xstat contains a plain signal number if the
 process is stopped, not a value that can be passed to WSTOPSIG.
 
 By the way, per POSIX, your test program needs #include <signal.h> for
 the CLD_EXITED constant.
 
 The test program (writes TAP output):
 
 /*-
  * Copyright (c) 2013 Jilles Tjoelker
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * $FreeBSD$
  */
 
 #include	<sys/resource.h>
 #include	<sys/wait.h>
 
 #include	<err.h>
 #include	<signal.h>
 #include	<stdio.h>
 #include	<unistd.h>
 
 static int testnum = 1;
 static int uid;
 
 static void
 dummy_handler_sa(int signum, siginfo_t *si, void *context)
 {
 }
 
 static void
 check_siginfo(const char *desc, siginfo_t *si, int sig, int sicode,
     int sistatus, pid_t pid)
 {
 	if (si->si_signo == SIGCHLD)
 		printf("ok %d - %s signal number\n", testnum++, desc);
 	else
 		printf("not ok %d - %s signal number %d != %d\n",
 		    testnum++, desc, si->si_signo, SIGCHLD);
 	if (si->si_code == sicode)
 		printf("ok %d - %s signal code %d\n",
 		    testnum++, desc, sicode);
 	else
 		printf("not ok %d - %s signal code %d != %d\n",
 		    testnum++, desc, si->si_code, sicode);
 	if (si->si_status == sistatus)
 		printf("ok %d - %s signal status %d\n",
 		    testnum++, desc, sistatus);
 	else
 		printf("not ok %d - %s signal status %d != %d\n",
 		    testnum++, desc, si->si_status, sistatus);
 	if (si->si_pid == pid)
 		printf("ok %d - %s signal pid %ld\n",
 		    testnum++, desc, (long)pid);
 	else
 		printf("not ok %d - %s signal pid %ld != %ld\n",
 		    testnum++, desc, (long)si->si_pid, (long)pid);
 	if (si->si_uid == uid)
 		printf("ok %d - %s signal UID %d\n",
 		    testnum++, desc, uid);
 	else
 		printf("not ok %d - %s signal UID %d != %d\n",
 		    testnum++, desc, si->si_uid, uid);
 }
 
 static void
 run_test(int sicode, int sistatus)
 {
 	int pid;
 	sigset_t sigs;
 	siginfo_t si;
 	int signum;
 
 	sigfillset(&sigs);
 	pid = fork();
 	if (pid == -1)
 		err(1, "fork");
 	if (pid == 0) {
 		switch (sicode) {
 		case CLD_EXITED:
 			_exit(sistatus);
 		case CLD_KILLED:
 		case CLD_DUMPED:
 			raise(sistatus);
 			fprintf(stderr, "raise(%d) returned!\n", sistatus);
 			_exit(255);
 		case CLD_STOPPED:
 			raise(sistatus);
 			sigsuspend(&sigs);
 			fprintf(stderr, "sigsuspend() returned!\n");
 			_exit(255);
 		default:
 			fprintf(stderr, "unexpected sicode %d!\n", sicode);
 			_exit(255);
 		}
 	}
 	signum = sigwaitinfo(&sigs, &si);
 	if (signum == -1)
 		err(1, "sigwaitinfo()");
 	if (signum != SIGCHLD)
 		errx(1, "sigwaitinfo() signal %d != %d", signum, SIGCHLD);
 	check_siginfo("sigwaitinfo", &si, SIGCHLD, sicode, sistatus, pid);
 	if (waitid(P_PID, pid, &si, WEXITED | WSTOPPED | WCONTINUED) != 0)
 		err(1, "waitid()");
 	check_siginfo("waitid", &si, SIGCHLD, sicode, sistatus, pid);
 	if (sicode == CLD_STOPPED) {
 		kill(pid, SIGCONT);
 		signum = sigwaitinfo(&sigs, &si);
 		if (signum == -1)
 			err(1, "sigwaitinfo()");
 		if (signum != SIGCHLD)
 			errx(1, "sigwaitinfo() signal %d != %d", signum, SIGCHLD);
 		check_siginfo("sigwaitinfo", &si, SIGCHLD,
 		    CLD_CONTINUED, SIGCONT, pid);
 		if (waitid(P_PID, pid, &si, WEXITED | WSTOPPED | WCONTINUED) !=
 		    0)
 			err(1, "waitid()");
 		check_siginfo("waitid", &si, SIGCHLD,
 		    CLD_CONTINUED, SIGCONT, pid);
 		kill(pid, SIGKILL);
 		if (waitpid(pid, NULL, 0) != pid)
 			errx(1, "waitpid");
 	}
 }
 
 int
 main(int argc, char *argv[])
 {
 	struct rlimit lim = {
 		.rlim_cur = RLIM_INFINITY,
 		.rlim_max = RLIM_INFINITY
 	};
 	struct sigaction sa;
 	sigset_t sigs;
 
 	printf("1..80\n");
 
 	if (setrlimit(RLIMIT_CORE, &lim) == -1)
 		err(1, "setrlimit(RLIMIT_CORE)");
 	sigemptyset(&sigs);
 	sigaddset(&sigs, SIGCHLD);
 	if (sigprocmask(SIG_BLOCK, &sigs, NULL) == -1)
 		err(1, "sigprocmask()");
 	sa.sa_sigaction = dummy_handler_sa;
 	sa.sa_flags = SA_RESTART | SA_SIGINFO;
 	sigemptyset(&sa.sa_mask);
 	if (sigaction(SIGCHLD, &sa, NULL) == -1)
 		err(1, "sigaction(SIGCHLD)");
 	uid = getuid();
 
 	run_test(CLD_EXITED, 0);
 	run_test(CLD_EXITED, 1);
 	run_test(CLD_EXITED, 42);
 	run_test(CLD_KILLED, SIGHUP);
 	run_test(CLD_KILLED, SIGUSR1);
 	run_test(CLD_DUMPED, SIGABRT);
 	run_test(CLD_STOPPED, SIGSTOP);
 
 	return 0;
 }
 
 /* vim:ts=8:cin:sw=8
  *  */
 
 The kernel patch:
 
 Index: sys/kern/kern_exit.c
 ===================================================================
 --- sys/kern/kern_exit.c	(revision 258178)
 +++ sys/kern/kern_exit.c	(working copy)
 @@ -974,16 +974,19 @@
  		 *  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
 Index: sys/kern/kern_sig.c
 ===================================================================
 --- sys/kern/kern_sig.c	(revision 258178)
 +++ sys/kern/kern_sig.c	(working copy)
 @@ -2959,7 +2959,7 @@
  }
  
  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 @@
  	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 @@
  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 @@
  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().
 
 -- 
 Jilles Tjoelker

From: Dmitrijs Ledkovs <xnox@debian.org>
To: Jilles Tjoelker <jilles@stack.nl>
Cc: bug-followup@freebsd.org
Subject: Re: kern/184002: wait6/waitid/SIGCHLD return wrong siginfo.si_status
Date: Sat, 16 Nov 2013 17:02:49 +0000

 On 16 November 2013 11:57, Jilles Tjoelker <jilles@stack.nl> wrote:
 > In PR kern/184002, you wrote:
 >> As per
 >> http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html
 >
 >> siginfo_t.si_status is "Exit value or signal."
 >
 >> The waitid call is suppose to fill in siginfo_t structure if one was
 >> passed to the function
 >> http://pubs.opengroup.org/onlinepubs/9699919799/functions/waitid.html
 >
 >> Instead at the moment the returned siginfo_t.si_status of FreeBSD is
 >> same on as &status returned by waitpid() call. I.E. value which hasn't
 >> been extraced with WEXITSTATUS()
 >
 > I have created and tested a patch for this issue. It is a bit trickier
 > than it seems because p_xstat contains a plain signal number if the
 > process is stopped, not a value that can be passed to WSTOPSIG.
 >
 > By the way, per POSIX, your test program needs #include <signal.h> for
 > the CLD_EXITED constant.
 >
 
 Ack. Thank you very much for proper test case & kernel patch.
 
 I've rebuild Debian kFreeBSD 10.x kernel with patch applied.
 I've tested your test-case program - it completes correct, all tests ok.
 I've tested libnih test-suite it now succeeds the failing test.
 
 Your patches work correct, and I will be waiting for them to be
 committed to head & stable branches to pick up those changes in
 Debian.
 
 Regards,
 
 Dmitrijs.

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/184002: commit references a PR
Date: Sun, 17 Nov 2013 22:31:37 +0000 (UTC)

 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-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: jilles 
State-Changed-When: Sun Dec 1 22:19:14 UTC 2013 
State-Changed-Why:  
Fixed in head. I plan to MFC to stable/10 and stable/9 after stable/10 
is reopened (this means the fix will not be in 10.0-RELEASE). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=184002 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/184002: commit references a PR
Date: Wed,  1 Jan 2014 20:22:36 +0000 (UTC)

 Author: jilles
 Date: Wed Jan  1 20:22:29 2014
 New Revision: 260164
 URL: http://svnweb.freebsd.org/changeset/base/260164
 
 Log:
   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
 
 Modified:
   stable/10/sys/kern/kern_exit.c
   stable/10/sys/kern/kern_sig.c
 Directory Properties:
   stable/10/   (props changed)
 
 Modified: stable/10/sys/kern/kern_exit.c
 ==============================================================================
 --- stable/10/sys/kern/kern_exit.c	Wed Jan  1 20:18:03 2014	(r260163)
 +++ stable/10/sys/kern/kern_exit.c	Wed Jan  1 20:22:29 2014	(r260164)
 @@ -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: stable/10/sys/kern/kern_sig.c
 ==============================================================================
 --- stable/10/sys/kern/kern_sig.c	Wed Jan  1 20:18:03 2014	(r260163)
 +++ stable/10/sys/kern/kern_sig.c	Wed Jan  1 20:22:29 2014	(r260164)
 @@ -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-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: jilles 
State-Changed-When: Fri Jan 3 14:31:53 UTC 2014 
State-Changed-Why:  
Fixed in 11-current, 10-stable and 9-stable. 
The wait6 code is not in 8-stable. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=184002 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/184002: commit references a PR
Date: Fri,  3 Jan 2014 14:30:31 +0000 (UTC)

 Author: jilles
 Date: Fri Jan  3 14:30:24 2014
 New Revision: 260227
 URL: http://svnweb.freebsd.org/changeset/base/260227
 
 Log:
   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
 
 Modified:
   stable/9/sys/kern/kern_exit.c
   stable/9/sys/kern/kern_sig.c
 Directory Properties:
   stable/9/sys/   (props changed)
 
 Modified: stable/9/sys/kern/kern_exit.c
 ==============================================================================
 --- stable/9/sys/kern/kern_exit.c	Fri Jan  3 12:28:33 2014	(r260226)
 +++ stable/9/sys/kern/kern_exit.c	Fri Jan  3 14:30:24 2014	(r260227)
 @@ -978,16 +978,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: stable/9/sys/kern/kern_sig.c
 ==============================================================================
 --- stable/9/sys/kern/kern_sig.c	Fri Jan  3 12:28:33 2014	(r260226)
 +++ stable/9/sys/kern/kern_sig.c	Fri Jan  3 14:30:24 2014	(r260227)
 @@ -2951,7 +2951,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;
  
 @@ -2971,7 +2971,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);
  }
 @@ -2979,6 +2979,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);
  }
  
 @@ -2992,13 +2993,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-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
