NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/58268: execve() discards pending signal



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

From: Noah Misch <noah%leadboat.com@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc: 
Subject: Re: kern/58268: execve() discards pending signal
Date: Sun, 10 Nov 2024 11:40:11 -0800

 Here is an improved version of the How-To-Repeat program.  The last version had
 undefined behavior due to an uninitialized sigset_t.  Fixing that made the
 REBLOCK variation irrelevant, so I've removed it.  I've also added a
 RAISE_AFTER_EXEC variation to further illustrate the NetBSD behavior.
 
 /*
  * Check whether exec() preserves pending signals
  * (https://pubs.opengroup.org/onlinepubs/9799919799/functions/exec.html).  The
  * program makes SIGTERM pending on itself, then self-execs a child that tests
  * sigpending().  Return value:
  *
  * 1 if SIGTERM pending
  * 2 if SIGTERM *not* pending
  * 90 if exec fails
  *
  * If the RAISE_AFTER_EXEC environment variable is set to any value, the program
  * instead does exec before making SIGTERM pending.
  *
  * Six systems return 1, with or without RAISE_AFTER_EXEC:
  *
  * AIX 7300-01-02-2320
  * Darwin 21.6.0
  * FreeBSD 14.0-release-p6
  * Linux 6.10.11-amd64
  * OpenBSD 7.5
  * Solaris 11.4.74.176.3
  *
  * NetBSD 10.0, 9.4, and 9.2 return 2.  They return 1 w/ RAISE_AFTER_EXEC.
  */
 #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);
 	if (!getenv("RAISE_AFTER_EXEC"))
 	    raise(SIGTERM);
 
 	execv(argv[0], cmd);
 	return 90;
     }
     else
     {
 	if (getenv("RAISE_AFTER_EXEC"))
 	{
 	    char msg[] = "reached write() w/ RAISE_AFTER_EXEC\n";
 
 	    raise(SIGTERM);
 	    write(2, msg, sizeof(msg) - 1);
 	}
 	else
 	{
 	    char msg[] = "reached write()\n";
 	    write(2, msg, sizeof(msg) - 1);
 	}
 	sigpending(&set);
 	return sigismember(&set, SIGTERM) ? 1 : 2;
     }
 }
 


Home | Main Index | Thread Index | Old Index