1 /* This testcase is part of GDB, the GNU debugger. 2 3 Copyright 2015 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 <pthread.h> 20 #include <unistd.h> 21 #include <stdio.h> 22 #include <sys/types.h> 23 #include <sys/wait.h> 24 #include <stdlib.h> 25 26 /* Number of threads. Each thread continuously spawns a fork and wait 27 for it. If we have another thread continuously start a step over, 28 gdbserver should end up finding new forks while suspending 29 threads. */ 30 #define NTHREADS 10 31 32 pthread_t threads[NTHREADS]; 33 34 pthread_barrier_t barrier; 35 36 #define NFORKS 10 37 38 /* Used to create a conditional breakpoint that always fails. */ 39 volatile int zero; 40 41 static void * 42 thread_forks (void *arg) 43 { 44 int i; 45 46 pthread_barrier_wait (&barrier); 47 48 for (i = 0; i < NFORKS; i++) 49 { 50 pid_t pid; 51 52 pid = fork (); 53 54 if (pid > 0) 55 { 56 int status; 57 58 /* Parent. */ 59 pid = waitpid (pid, &status, 0); 60 if (pid == -1) 61 { 62 perror ("wait"); 63 exit (1); 64 } 65 66 if (!WIFEXITED (status)) 67 { 68 printf ("Unexpected wait status 0x%x from child %d\n", 69 status, pid); 70 } 71 } 72 else if (pid == 0) 73 { 74 /* Child. */ 75 exit (0); 76 } 77 else 78 { 79 perror ("fork"); 80 exit (1); 81 } 82 } 83 } 84 85 /* Set this to tell the thread_breakpoint thread to exit. */ 86 volatile int break_out; 87 88 static void * 89 thread_breakpoint (void *arg) 90 { 91 pthread_barrier_wait (&barrier); 92 93 while (!break_out) 94 { 95 usleep (1); /* set break here */ 96 } 97 98 return NULL; 99 } 100 101 pthread_barrier_t barrier; 102 103 int 104 main (void) 105 { 106 int i; 107 int ret; 108 pthread_t bp_thread; 109 110 /* Don't run forever. */ 111 alarm (180); 112 113 pthread_barrier_init (&barrier, NULL, NTHREADS + 1); 114 115 /* Start the threads that constantly fork. */ 116 for (i = 0; i < NTHREADS; i++) 117 { 118 ret = pthread_create (&threads[i], NULL, thread_forks, NULL); 119 assert (ret == 0); 120 } 121 122 /* Start the thread that constantly hit a conditional breakpoint 123 that needs to be stepped over. */ 124 ret = pthread_create (&bp_thread, NULL, thread_breakpoint, NULL); 125 assert (ret == 0); 126 127 /* Wait for forking to stop. */ 128 for (i = 0; i < NTHREADS; i++) 129 { 130 ret = pthread_join (threads[i], NULL); 131 assert (ret == 0); 132 } 133 134 break_out = 1; 135 pthread_join (bp_thread, NULL); 136 assert (ret == 0); 137 138 return 0; 139 } 140