1 /* This testcase is part of GDB, the GNU debugger. 2 3 Copyright 2016-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 <pthread.h> 19 #include <unistd.h> 20 #include <stdlib.h> 21 #include <stdio.h> 22 #include <sys/types.h> 23 #include <sys/wait.h> 24 #include <assert.h> 25 #include <errno.h> 26 #include <string.h> 27 28 /* This barrier ensures we only reach the initial breakpoint after all 29 threads have started. */ 30 pthread_barrier_t start_threads_barrier; 31 32 /* Many threads in order to be fairly sure the process exits while GDB 33 is detaching from each thread in the process, on targets that need 34 to detach from each thread individually. */ 35 #define NTHREADS 256 36 37 /* GDB sets a watchpoint here. */ 38 int globalvar = 1; 39 40 /* GDB reads this. */ 41 int mypid; 42 43 /* Threads' entry point. */ 44 45 void * 46 thread_function (void *arg) 47 { 48 pthread_barrier_wait (&start_threads_barrier); 49 _exit (0); 50 } 51 52 /* The fork child's entry point. */ 53 54 void 55 child_function (void) 56 { 57 pthread_t threads[NTHREADS]; 58 int i; 59 60 pthread_barrier_init (&start_threads_barrier, NULL, NTHREADS + 1); 61 62 for (i = 0; i < NTHREADS; i++) 63 pthread_create (&threads[i], NULL, thread_function, NULL); 64 pthread_barrier_wait (&start_threads_barrier); 65 66 exit (0); 67 } 68 69 /* This is defined by the .exp file if testing the multi-process 70 variant. */ 71 #ifdef MULTIPROCESS 72 73 /* The fork parent's entry point. */ 74 75 void 76 parent_function (pid_t child) 77 { 78 int status, ret; 79 80 alarm (300); 81 82 ret = waitpid (child, &status, 0); 83 84 if (ret == -1) 85 { 86 printf ("waitpid, errno=%d (%s)\n", errno, strerror (errno)); 87 exit (1); 88 } 89 else if (WIFEXITED (status)) 90 { 91 printf ("exited, status=%d\n", WEXITSTATUS (status)); 92 exit (0); 93 } 94 else if (WIFSIGNALED (status)) 95 { 96 printf ("signaled, sig=%d\n", WTERMSIG (status)); 97 exit (2); 98 } 99 else 100 { 101 printf ("unexpected, status=%x\n", status); 102 exit (3); 103 } 104 } 105 106 #endif 107 108 int 109 main (void) 110 { 111 #ifdef MULTIPROCESS 112 pid_t child; 113 114 child = fork (); 115 if (child == -1) 116 return 1; 117 #endif 118 119 mypid = getpid (); 120 121 #ifdef MULTIPROCESS 122 if (child != 0) 123 parent_function (child); 124 else 125 #endif 126 child_function (); 127 128 /* Not reached. */ 129 abort (); 130 } 131