From d68b1cefd50125f3ecf3e4b0e833f068c90b6ed0 Mon Sep 17 00:00:00 2001 From: claudio Date: Mon, 7 Oct 2024 14:01:12 +0000 Subject: [PATCH] Add a multithreaded test for SIGSTOP and SIGCONT behaviour. This actually installs a SIGTSTP handler which then triggers a SIGSTOP. Currently unlinked since both SIGSTOP and SIGCONT delivery is busted. --- regress/sys/kern/signal/sig-stop2/Makefile | 7 + regress/sys/kern/signal/sig-stop2/sig-stop2.c | 137 ++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 regress/sys/kern/signal/sig-stop2/Makefile create mode 100644 regress/sys/kern/signal/sig-stop2/sig-stop2.c diff --git a/regress/sys/kern/signal/sig-stop2/Makefile b/regress/sys/kern/signal/sig-stop2/Makefile new file mode 100644 index 00000000000..e0a93d7c632 --- /dev/null +++ b/regress/sys/kern/signal/sig-stop2/Makefile @@ -0,0 +1,7 @@ +# $OpenBSD: Makefile,v 1.1 2024/10/07 14:01:12 claudio Exp $ + +PROG= sig-stop2 + +LDADD= -lpthread + +.include diff --git a/regress/sys/kern/signal/sig-stop2/sig-stop2.c b/regress/sys/kern/signal/sig-stop2/sig-stop2.c new file mode 100644 index 00000000000..9486ed9e450 --- /dev/null +++ b/regress/sys/kern/signal/sig-stop2/sig-stop2.c @@ -0,0 +1,137 @@ +/* $OpenBSD: sig-stop2.c,v 1.1 2024/10/07 14:01:12 claudio Exp $ */ +/* + * Written by Artur Grabowski 2007 Public Domain. + * Written by Claudio Jeker 2024 Public Domain. + */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define THREAD_COUNT 4 + +volatile sig_atomic_t tstp_count, cont_count; +pid_t child; + +static void +tstp_handler(int sig) +{ + tstp_count++; + dprintf(STDERR_FILENO, "SIGTSTP\n"); + kill(getpid(), SIGSTOP); +} + +static void +cont_handler(int sig) +{ + dprintf(STDERR_FILENO, "SIGCONT\n"); + cont_count++; +} + +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; + + signal(SIGTSTP, tstp_handler); + signal(SIGCONT, cont_handler); + + sigemptyset(&set); + sigaddset(&set, SIGTSTP); + sigaddset(&set, SIGCONT); + + self = pthread_self(); + 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; + } + } + + sigprocmask(SIG_BLOCK, &set, NULL); + + for (i = 0; i < THREAD_COUNT; i++) { + if (!pthread_equal(pthread[i], self) && + (r = pthread_join(pthread[i], NULL))) + warnc(r, "could not join thread"); + } + + printf("#tstp = %d #cont = %d\n", tstp_count, cont_count); + + return !(tstp_count == 1 && cont_count == 1); +} + +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); + + if (kill(child, SIGTSTP) == -1) + err(1, "kill"); + + if (waitpid(child, &status, WCONTINUED|WUNTRACED) <= 0) + err(1, "waitpid"); + + nanosleep(&ts, NULL); + + if (kill(child, SIGCONT) == -1) + err(1, "kill"); + + if (waitpid(child, &status, WCONTINUED|WUNTRACED) <= 0) + err(1, "waitpid"); + + nanosleep(&ts, NULL); + + if (waitpid(child, &status, 0) <= 0) + err(1, "waitpid"); + + if (!WIFEXITED(status)) + err(1, "bad status: %d", status); + + return WEXITSTATUS(status); +} -- 2.20.1