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