>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:
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "[email protected]"

Reply via email to