Add regress test that sends a SIGSTOP to a child whit its mainproc gone.
authorclaudio <claudio@openbsd.org>
Wed, 9 Oct 2024 12:59:59 +0000 (12:59 +0000)
committerclaudio <claudio@openbsd.org>
Wed, 9 Oct 2024 12:59:59 +0000 (12:59 +0000)
Right now this fails since dowait6() depends on ps_mainproc for this.

regress/sys/kern/signal/sig-stop3/Makefile [new file with mode: 0644]
regress/sys/kern/signal/sig-stop3/sig-stop3.c [new file with mode: 0644]

diff --git a/regress/sys/kern/signal/sig-stop3/Makefile b/regress/sys/kern/signal/sig-stop3/Makefile
new file mode 100644 (file)
index 0000000..a3fdcc3
--- /dev/null
@@ -0,0 +1,7 @@
+#      $OpenBSD: Makefile,v 1.1 2024/10/09 12:59:59 claudio Exp $
+
+PROG=  sig-stop3
+
+LDADD= -lpthread
+
+.include <bsd.regress.mk>
diff --git a/regress/sys/kern/signal/sig-stop3/sig-stop3.c b/regress/sys/kern/signal/sig-stop3/sig-stop3.c
new file mode 100644 (file)
index 0000000..088765c
--- /dev/null
@@ -0,0 +1,108 @@
+/*     $OpenBSD: sig-stop3.c,v 1.1 2024/10/09 12:59:59 claudio Exp $   */
+/*
+ *     Written by Artur Grabowski <art@openbsd.org> 2007 Public Domain.
+ *     Written by Claudio Jeker <claudio@openbsd.org> 2024 Public Domain.
+ */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <time.h>
+#include <err.h>
+#include <signal.h>
+#include <pthread.h>
+
+#define        THREAD_COUNT    4
+
+volatile sig_atomic_t tstp_count, cont_count;
+pid_t child;
+
+static void
+alrm_handler(int sig)
+{
+       kill(child, SIGKILL);
+       dprintf(STDERR_FILENO, "timeout\n");
+       _exit(2);
+}
+
+
+static void *
+thread(void *arg)
+{
+       struct timespec ts = { .tv_sec = 2 };
+
+       while (nanosleep(&ts, &ts) != 0)
+               ;
+
+       return NULL;
+}
+
+static int
+child_main(void)
+{
+       pthread_t self, pthread[THREAD_COUNT];
+       sigset_t set;
+       int i, r;
+
+       for (i = 0; i < THREAD_COUNT; i++) {
+               if ((r = pthread_create(&pthread[i], NULL, thread, NULL))) {
+                       warnc(r, "could not create thread");
+                       pthread[i] = self;
+               }
+       }
+
+       /* terminate main process */
+       pthread_exit(NULL);
+}
+
+int
+main(int argc, char **argv)
+{
+       struct timespec ts = { .tv_nsec = 200 * 1000 * 1000 };
+       int status;
+
+       switch((child = fork())) {
+       case -1:
+               err(1, "fork");
+       case 0:
+               exit(child_main());
+       default:
+               break;
+       }
+
+       signal(SIGALRM, alrm_handler);
+       alarm(5);
+
+       nanosleep(&ts, NULL);
+
+       printf("sending SIGSTOP\n");
+       if (kill(child, SIGSTOP) == -1)
+               err(1, "kill");
+
+       printf("waiting...\n");
+       if (waitpid(child, &status, WCONTINUED|WUNTRACED) <= 0)
+               err(1, "waitpid");
+
+       if (!WIFSTOPPED(status))
+               errx(1, "bad status, not stopped: %d", status);
+       printf("got stopped notification\n");
+
+       nanosleep(&ts, NULL);
+
+       printf("killing child\n");
+       if (kill(child, SIGKILL) == -1)
+               err(1, "kill");
+
+       if (waitpid(child, &status, 0) <= 0)
+               err(1, "waitpid");
+
+       if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGKILL)
+               errx(1, "bad status: %d", status);
+
+       printf("OK\n");
+       return 0;
+}