misc/184002: wait6 / waitid returns wrong value in siginfo.si_status

Dmitrijs Ledkovs xnox at debian.org
Fri Nov 15 15:30:01 UTC 2013


>Number:         184002
>Category:       misc
>Synopsis:       wait6 / waitid returns wrong value in siginfo.si_status
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Nov 15 15:30:00 UTC 2013
>Closed-Date:
>Last-Modified:
>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:
>Unformatted:


More information about the freebsd-bugs mailing list