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