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