1 /* This testcase is part of GDB, the GNU debugger. 2 3 Copyright 2021-2023 Free Software Foundation, Inc. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18 #include <assert.h> 19 #include <errno.h> 20 #include <poll.h> 21 #include <pthread.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <sys/wait.h> 26 #include <unistd.h> 27 28 #define NUM_FORKING_THREADS 12 29 30 static pthread_barrier_t barrier; 31 static volatile int should_exit = 0; 32 33 static void 34 sigusr1_handler (int sig, siginfo_t *siginfo, void *context) 35 { 36 should_exit = 1; 37 } 38 39 static void * 40 forking_thread (void *arg) 41 { 42 /* Wait for all forking threads to have spawned before fork-spamming. */ 43 pthread_barrier_wait (&barrier); 44 45 while (!should_exit) 46 { 47 pid_t pid = fork (); 48 if (pid == 0) 49 { 50 /* Child */ 51 exit (8); 52 } 53 else 54 { 55 /* Parent */ 56 int status; 57 int ret = waitpid (pid, &status, 0); 58 assert (ret == pid); 59 assert (WIFEXITED (status)); 60 assert (WEXITSTATUS (status) == 8); 61 } 62 } 63 64 return NULL; 65 } 66 67 static void 68 break_here_first (void) 69 { 70 } 71 72 static pid_t my_pid; 73 74 int 75 main (void) 76 { 77 pthread_t forking_threads[NUM_FORKING_THREADS]; 78 int ret; 79 struct sigaction sa; 80 int i; 81 82 /* Just to make sure we don't run for ever. */ 83 alarm (30); 84 85 my_pid = getpid (); 86 87 break_here_first (); 88 89 pthread_barrier_init (&barrier, NULL, NUM_FORKING_THREADS); 90 91 memset (&sa, 0, sizeof (sa)); 92 sa.sa_sigaction = sigusr1_handler; 93 ret = sigaction (SIGUSR1, &sa, NULL); 94 assert (ret == 0); 95 96 for (i = 0; i < NUM_FORKING_THREADS; ++i) 97 { 98 ret = pthread_create (&forking_threads[i], NULL, forking_thread, NULL); 99 assert (ret == 0); 100 } 101 102 for (i = 0; i < NUM_FORKING_THREADS; ++i) 103 { 104 ret = pthread_join (forking_threads[i], NULL); 105 assert (ret == 0); 106 } 107 108 FILE *f = fopen (TOUCH_FILE_PATH, "w"); 109 assert (f != NULL); 110 ret = fclose (f); 111 assert (ret == 0); 112 113 return 0; 114 } 115