Issue with kill after exec in testsuite

Jeremy Drake cygwin@jdrake.com
Tue Jul 8 19:02:44 GMT 2025


I've run into an odd issue with exec and kill in winsup/testsuite that
doesn't happen in a more normal configuration.  What I'm doing is getting
the pid via getpid (), then forking.  In the forked child, I can call kill
(pid, SIGUSR1) without issue, but if instead I call execv (passing the
pid as an argument) and then call kill after the exec I get "No such
process" error.  Can anyone tell what I'm doing wrong?

Here's the test output:
kill after exec: No such process
SUCCESS: The process with PID 3748 (child process of PID 5984) has been terminated.
Timeout
FAIL winsup.api/killissue.exe (exit status: 124)

And here's a test with the working fork/kill if 0'ed out and the broken
fork/exec/kill in place:

Subject: [RFC PATCH] Cygwin: testsuite: test odd issue with kill

kill of parent pid works in forked child, but not after exec?  Only in
testsuite though.

Signed-off-by: Jeremy Drake <cygwin@jdrake.com>
---
 winsup/testsuite/Makefile.am            |   1 +
 winsup/testsuite/winsup.api/killissue.c | 117 ++++++++++++++++++++++++
 2 files changed, 118 insertions(+)
 create mode 100644 winsup/testsuite/winsup.api/killissue.c

diff --git a/winsup/testsuite/Makefile.am b/winsup/testsuite/Makefile.am
index 20e06b9c51..b3c30be181 100644
--- a/winsup/testsuite/Makefile.am
+++ b/winsup/testsuite/Makefile.am
@@ -37,6 +37,7 @@ check_PROGRAMS = \
 	winsup.api/devdsp \
 	winsup.api/devzero \
 	winsup.api/iospeed \
+	winsup.api/killissue \
 	winsup.api/mmaptest01 \
 	winsup.api/mmaptest02 \
 	winsup.api/mmaptest03 \
diff --git a/winsup/testsuite/winsup.api/killissue.c b/winsup/testsuite/winsup.api/killissue.c
new file mode 100644
index 0000000000..c5b397f090
--- /dev/null
+++ b/winsup/testsuite/winsup.api/killissue.c
@@ -0,0 +1,117 @@
+#define _GNU_SOURCE
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+int main (int argc, char **argv)
+{
+  sigset_t set, oldset;
+  int ret = 0, status;
+  pid_t pid, childpid;
+
+  if (argc == 3 && !strcmp (argv[1], "--child"))
+    {
+      if (kill (atoi (argv[2]), SIGUSR1) == -1)
+	{
+	  perror ("kill after exec");
+	  return 1;
+	}
+
+      usleep (100000);
+      return 0;
+    }
+
+  pid = getpid ();
+
+  sigemptyset (&set);
+  sigaddset (&set, SIGUSR1);
+  errno = 0;
+  sigprocmask (SIG_BLOCK, &set, &oldset);
+
+#if 0
+  switch ((childpid = fork ()))
+  {
+  case -1:
+    perror ("fork");
+    ret |= 1;
+    break;
+  case 0:
+    /* child */
+    if (kill (pid, SIGUSR1) == -1)
+      {
+	perror ("kill without exec");
+	return 1;
+      }
+    return 0;
+  default:
+    /* parent */
+    while (1)
+      {
+	int sig;
+	if (sigwait (&set, &sig))
+	  {
+	    perror ("sigwait");
+	    return 2;
+	  }
+	if (sig == SIGUSR1)
+	  break;
+      }
+    if (waitpid (childpid, &status, 0) == -1)
+      {
+	perror ("waitpid");
+	ret |= 1;
+      }
+    else if (WIFEXITED (status))
+      ret |= WEXITSTATUS (status);
+    else if (WIFSIGNALED (status))
+      ret |= WTERMSIG (status);
+  }
+#endif
+
+  switch ((childpid = fork ()))
+  {
+  case -1:
+    perror ("fork");
+    ret |= 1;
+    break;
+  case 0:
+    /* child */
+    {
+      char buf[16];
+      char *childargs[] = {"/proc/self/exe", "--child", buf, NULL};
+      sprintf (buf, "%d", pid);
+      execv (childargs[0], childargs);
+      perror ("execv");
+    }
+    return 1;
+  default:
+    /* parent */
+    while (1)
+      {
+	int sig;
+	if (sigwait (&set, &sig))
+	  {
+	    perror ("sigwait");
+	    return 2;
+	  }
+	if (sig == SIGUSR1)
+	  break;
+      }
+    if (waitpid (childpid, &status, 0) == -1)
+      {
+	perror ("waitpid");
+	ret |= 1;
+      }
+    else if (WIFEXITED (status))
+      ret |= WEXITSTATUS (status);
+    else if (WIFSIGNALED (status))
+      ret |= WTERMSIG (status);
+  }
+  sigprocmask (SIG_SETMASK, &oldset, NULL);
+
+  return ret;
+}
-- 
2.50.1.windows.1



More information about the Cygwin-developers mailing list