NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/58268: execve() discards pending signal
>Number: 58268
>Category: kern
>Synopsis: execve() discards pending signal
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon May 20 04:30:00 +0000 2024
>Originator: Noah Misch
>Release: 9.2, 9.4, 10.0
>Organization:
>Environment:
NetBSD 10.0 NetBSD 10.0 (GENERIC) #0: Thu Mar 28 08:33:33 UTC 2024 mkrepro%mkrepro.NetBSD.org@localhost:/usr/src/sys/arch/amd64/compile/GENERIC amd64
>Description:
https://pubs.opengroup.org/onlinepubs/9699919799/functions/execve.html says the
new process inherits "pending signal". Per the below test program, a signal
pending before execve() is neither delivered nor pending after execve(). The
test program observed this in NetBSD 9.2, 9.4 and 10.0. The other operating
systems I tested keep the signal pending; the test program header comment lists
them.
[non-essential background info] I discovered this in the context of
https://github.com/cpan-authors/IPC-Run/issues/175, where an IPC::Run test case
can make kill(KID, SIGTERM) overlap KID running exec(). The IPC::Run test never
runs kill() before exec(), always during exec() or after exec(). Hence, it's
different from the below C program, which makes the signal pending before
exec(). The IPC::Run test case was stable on NetBSD until NetBSD 10.0.
Starting with NetBSD 10.0, the IPC::Run SIGTERM is usually lost. Perhaps NetBSD
10.0 expanded the ability of actions to interrupt exec(). That's fine.
>How-To-Repeat:
/*
* Return value:
* 1 if sigprocmask(SIG_UNBLOCK) returns w/ SIGTERM pending
* 2 if sigprocmask(SIG_UNBLOCK) returns w/ SIGTERM *not* pending
* 90 if exec fails
*
* AIX 7300-01-02-2320: returns 1 always. Compiling with -DREBLOCK makes it die
* to SIGTERM always.
*
* Same as AIX:
* Darwin 21.6.0
* FreeBSD 14.0-release-p6
* Linux 6.7.12-amd64
* OpenBSD 7.5
* Solaris 11.4.68.164.2
*
* NetBSD 10.0, 9.4, 9.2: returns 2 always.
*
* Linux 3.10.0-1160.99.1.el7.x86_64: Dies to SIGTERM about half the time,
* returning 1 the other half. Compiling with -DREBLOCK makes it die to SIGTERM
* always.
*/
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
sigset_t set;
if (argc == 1)
{
char *cmd[] = { argv[0], "anything", (char *)0 };
sigemptyset(&set);
sigaddset(&set, SIGTERM);
sigprocmask(SIG_BLOCK, &set, NULL);
raise(SIGTERM);
execv(argv[0], cmd);
return 90;
}
else
{
char msg[] = "reached write()\n";
#if REBLOCK
sigemptyset(&set);
sigaddset(&set, SIGTERM);
sigprocmask(SIG_BLOCK, &set, NULL);
#endif
write(2, msg, sizeof(msg) - 1);
sigprocmask(SIG_UNBLOCK, &set, NULL);
sigpending(&set);
return sigismember(&set, SIGTERM) ? 1 : 2;
}
}
>Fix:
not known
Home |
Main Index |
Thread Index |
Old Index