xref: /openbsd-src/regress/sys/kern/signal/sig-stop3/sig-stop3.c (revision 53b677a8a339f16b5136c6ea4600f5279ead9fbc)
1 /*	$OpenBSD: sig-stop3.c,v 1.1 2024/10/09 12:59:59 claudio Exp $	*/
2 /*
3  *	Written by Artur Grabowski <art@openbsd.org> 2007 Public Domain.
4  *	Written by Claudio Jeker <claudio@openbsd.org> 2024 Public Domain.
5  */
6 #include <sys/types.h>
7 #include <sys/time.h>
8 #include <sys/wait.h>
9 
10 #include <err.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <time.h>
15 #include <err.h>
16 #include <signal.h>
17 #include <pthread.h>
18 
19 #define	THREAD_COUNT	4
20 
21 volatile sig_atomic_t tstp_count, cont_count;
22 pid_t child;
23 
24 static void
25 alrm_handler(int sig)
26 {
27 	kill(child, SIGKILL);
28 	dprintf(STDERR_FILENO, "timeout\n");
29 	_exit(2);
30 }
31 
32 
33 static void *
34 thread(void *arg)
35 {
36 	struct timespec ts = { .tv_sec = 2 };
37 
38 	while (nanosleep(&ts, &ts) != 0)
39 		;
40 
41 	return NULL;
42 }
43 
44 static int
45 child_main(void)
46 {
47 	pthread_t self, pthread[THREAD_COUNT];
48 	sigset_t set;
49 	int i, r;
50 
51 	for (i = 0; i < THREAD_COUNT; i++) {
52 		if ((r = pthread_create(&pthread[i], NULL, thread, NULL))) {
53 			warnc(r, "could not create thread");
54 			pthread[i] = self;
55 		}
56 	}
57 
58 	/* terminate main process */
59 	pthread_exit(NULL);
60 }
61 
62 int
63 main(int argc, char **argv)
64 {
65 	struct timespec ts = { .tv_nsec = 200 * 1000 * 1000 };
66 	int status;
67 
68 	switch((child = fork())) {
69 	case -1:
70 		err(1, "fork");
71 	case 0:
72 		exit(child_main());
73 	default:
74 		break;
75 	}
76 
77 	signal(SIGALRM, alrm_handler);
78 	alarm(5);
79 
80 	nanosleep(&ts, NULL);
81 
82 	printf("sending SIGSTOP\n");
83 	if (kill(child, SIGSTOP) == -1)
84 		err(1, "kill");
85 
86 	printf("waiting...\n");
87 	if (waitpid(child, &status, WCONTINUED|WUNTRACED) <= 0)
88 		err(1, "waitpid");
89 
90 	if (!WIFSTOPPED(status))
91 		errx(1, "bad status, not stopped: %d", status);
92 	printf("got stopped notification\n");
93 
94 	nanosleep(&ts, NULL);
95 
96 	printf("killing child\n");
97 	if (kill(child, SIGKILL) == -1)
98 		err(1, "kill");
99 
100 	if (waitpid(child, &status, 0) <= 0)
101 		err(1, "waitpid");
102 
103 	if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGKILL)
104 		errx(1, "bad status: %d", status);
105 
106 	printf("OK\n");
107 	return 0;
108 }
109