1 /* This testcase is part of GDB, the GNU debugger. 2 3 Copyright 2014-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 <signal.h> 20 #include <stdlib.h> 21 #include <unistd.h> 22 23 /* Used to individually advance each thread to the desired stopping point. */ 24 int ready; 25 26 sig_atomic_t sigusr1_received; 27 sig_atomic_t sigusr2_received; 28 sig_atomic_t sigabrt_received; 29 30 /* Number of threads currently running. */ 31 int thread_count; 32 pthread_mutex_t thread_count_mutex; 33 pthread_cond_t thread_count_condvar; 34 35 static void 36 incr_thread_count (void) 37 { 38 pthread_mutex_lock (&thread_count_mutex); 39 ++thread_count; 40 pthread_cond_signal (&thread_count_condvar); 41 pthread_mutex_unlock (&thread_count_mutex); 42 } 43 44 static void 45 sigusr1_handler (int sig) 46 { 47 sigusr1_received = 1; 48 } 49 50 static void 51 sigusr2_handler (int sig) 52 { 53 sigusr2_received = 1; 54 } 55 56 static void 57 sigabrt_handler (int sig) 58 { 59 sigabrt_received = 1; 60 } 61 62 static void * 63 sigusr1_thread_function (void *unused) 64 { 65 incr_thread_count (); 66 while (!ready) 67 usleep (100); 68 pthread_kill (pthread_self (), SIGUSR1); 69 } 70 71 static void * 72 sigusr2_thread_function (void *unused) 73 { 74 incr_thread_count (); 75 while (!ready) 76 usleep (100); 77 /* pthread_kill (pthread_self (), SIGUSR2); - manually injected by gdb */ 78 } 79 80 /* Wait until all threads are at a point where a backtrace will 81 show the thread entry point function. */ 82 83 static void 84 wait_all_threads_running (int nr_threads) 85 { 86 pthread_mutex_lock (&thread_count_mutex); 87 88 while (1) 89 { 90 if (thread_count == nr_threads) 91 { 92 pthread_mutex_unlock (&thread_count_mutex); 93 return; 94 } 95 pthread_cond_wait (&thread_count_condvar, &thread_count_mutex); 96 } 97 } 98 99 static void 100 all_threads_running (void) 101 { 102 while (!ready) 103 usleep (100); 104 } 105 106 static void 107 all_threads_done (void) 108 { 109 } 110 111 int 112 main () 113 { 114 pthread_t sigusr1_thread, sigusr2_thread; 115 116 /* Protect against running forever. */ 117 alarm (60); 118 119 signal (SIGUSR1, sigusr1_handler); 120 signal (SIGUSR2, sigusr2_handler); 121 signal (SIGABRT, sigabrt_handler); 122 123 /* Don't let any thread advance past initialization. */ 124 ready = 0; 125 126 pthread_mutex_init (&thread_count_mutex, NULL); 127 pthread_cond_init (&thread_count_condvar, NULL); 128 129 #define NR_THREADS 2 130 pthread_create (&sigusr1_thread, NULL, sigusr1_thread_function, NULL); 131 pthread_create (&sigusr2_thread, NULL, sigusr2_thread_function, NULL); 132 wait_all_threads_running (NR_THREADS); 133 all_threads_running (); 134 135 pthread_kill (pthread_self (), SIGABRT); 136 137 pthread_join (sigusr1_thread, NULL); 138 pthread_join (sigusr2_thread, NULL); 139 all_threads_done (); 140 141 return 0; 142 } 143