kern/19402: Signals 127 and 128 cannot be detected in wait4() interface

Bruce Evans brde at
Mon Apr 30 08:30:18 UTC 2012

The following reply was made to PR kern/19402; it has been noted by GNATS.

From: Bruce Evans <brde at>
To: Jilles Tjoelker <jilles at>
Cc: bug-followup at, netch at, bde at
Subject: Re: kern/19402: Signals 127 and 128 cannot be detected in wait4()
Date: Mon, 30 Apr 2012 18:24:51 +1000 (EST)

 On Mon, 30 Apr 2012, Jilles Tjoelker wrote:
 >> [problems with signals 127 and 128]
 > First, note that "clean" programs cannot use signals 127 and 128 because
 > they do neither have a SIG* constant nor are in the range SIGRTMIN to
 > SIGRTMAX. Therefore, I think it is inappropriate to make large changes
 > to make them work. It suffices if wait4() and other interfaces cannot
 > cause confusion.
 I agree with not making large changes, of course.
 I wonder if there is a technical reason why 127 and and 128 were left out
 of SIGRTMAX.  In 4.4BSD, NSIG was only 32, with a comment saying that 33
 is possible (since NSIG counts signal 0).  Signal 32 would have caused
 fewer problems than signal 128 does now, but was left out.  In Linux
 (2.6.10 for x86-64, i386 and many others), NSIG is 32 and _NSIG is 64;
 apparently NSIG counts signal 0 but _NSIG doesn't, similarly to
 FreeBSD except for the spelling and value of _NSIG and all signals up
 to and including _NSIG being supported (SIGRTMIN is NSIG = 32 and
 SIGRTMAX is _NSIG = 64; FreeBSD uses the better spelling _SIG_MAXSIG
 for _NSIG); a max of 64 causes fewer technical problems and less bloat.
 > Because sh returns exit status 128+sig for signal sig, signal 128 cannot
 > be represented in an 8-bit exit status and would have to be aliased to
 > another signal if it is kept.
 > The suggestion to modify wait4() ABI seems inappropriate for that
 > reason.
 > Another option is to modify the highest signal number accepted by
 > interfaces (while leaving the size of sigset_t and the like unchanged).
 > This effectively removes signals 127 and 128 from the system. One
 > problem results when having posix_spawn() from an old libc reset all
 > signals to default (by passing posix_spawnattr_setsigdefault() a
 > sigfillset()'ed sigset_t and enabling the POSIX_SPAWN_SETSIGDEF flag in
 > the posix_spawnattr_t). It will then attempt to set all signals from 1
 > to 128 to the default action and fail the entire spawn if sigaction()
 > fails. This could be allowed by having certain calls (such as
 > sigaction() with SIG_DFL) return success without doing anything for
 > signals 127 and 128. This is likely to get messy.
 > Alternatively, the default action for signals 127 and 128 could be
 > changed to ignore (like SIGCHLD, SIGURG and SIGINFO), so that no process
 > may terminate because of them. Processes can still send the signals and
 > set handlers for them. Apart from the obvious effect that the process
 > will not terminate when it receives such a signal without handling or
 > masking it, FreeBSD also discards ignored signals even when they are
 > masked (POSIX permits this). This could lead to unexpected results if a
 > process is using sigwait() or a similar function.
 > Yet another approach would modify the wait4() system call, changing
 > signals 127 and 128 to something that does not cause confusion. This
 > seems ugly.
 I think I prefer disallowing signal 128 and not worry about unportable
 programs using it, and not changing anything for signal 127 and not worry
 about the ambiguous wait status from this.
 Emulators give interesting problems with signal ranges.  FreeBSD seems
 to handle these problems mostly correctly in the Linux emulator.  First,
 it needs a host signal range larger than the target signal range.
 [0..126], [0..127] and [0..128] all exceed the Linux range of [0..64],
 so there is no problem yet.  However, for mips under Linux, _NSIG is 128,
 so the full FreeBSD range might be needed, depending on how Linux handles
 the problem with wait statuses.   FreeBSD mostly uses the Linux _NSIG
 correctly, so it gets target limits.  It also translates signal numbers
 below NSIG, so it knows a little about NSIG counting signal 0.  However,
 in linux_ioctl.c, it still uses the old FreeBSD signal number NSIG in a
 private ISSIGVALID() macro instead of using its standard macro
 LINUX_SIG_VALID() which uses _NSIG correctly.  ISSIGVALID() is only used
 for the VT_SETMODE ioctl, and FreeBSD's signal handling for this differs
 in other ways than Linux's (FreeBSD fixes up mode.frsig (but only if it
 and mode.acqsig are invalid according to the private macro), while Linux
 ignores mode.frsig.  The private macro might even be correct, with making
 it look like a standard macro just obfuscating any magic for NSIG here.

More information about the freebsd-bugs mailing list