|  | /* Test case for C-c sent to threads with pending signals.  Before I | 
|  | even get there, creating a thread and sending it a signal before it | 
|  | has a chance to run leads to an internal error in GDB.  We need to | 
|  | record that there's a pending SIGSTOP, so that we'll ignore it | 
|  | later, and pass the current signal back to the thread. | 
|  |  | 
|  | The fork/vfork case has similar trouble but that's even harder | 
|  | to get around.  We may need to send a SIGCONT to cancel out the | 
|  | SIGSTOP.  Different kernels may do different things if the thread | 
|  | is stopped by ptrace and sent a SIGSTOP.  */ | 
|  |  | 
|  | #include <stdio.h> | 
|  | #include <unistd.h> | 
|  | #include <stdlib.h> | 
|  | #include <pthread.h> | 
|  | #include <signal.h> | 
|  |  | 
|  | /* Loop long enough for GDB to send a few signals of its own, but | 
|  | don't hang around eating CPU forever if something goes wrong during | 
|  | testing.  */ | 
|  | #define NSIGS 10000000 | 
|  |  | 
|  | pthread_barrier_t barrier; | 
|  |  | 
|  | void | 
|  | handler (int sig) | 
|  | { | 
|  | ; | 
|  | } | 
|  |  | 
|  | pthread_t main_thread; | 
|  | pthread_t child_thread, child_thread_two; | 
|  |  | 
|  | void * | 
|  | child_two (void *arg) | 
|  | { | 
|  | int i; | 
|  |  | 
|  | pthread_barrier_wait (&barrier); | 
|  |  | 
|  | for (i = 0; i < NSIGS; i++) | 
|  | pthread_kill (child_thread, SIGUSR1); | 
|  | } | 
|  |  | 
|  | void * | 
|  | thread_function (void *arg) | 
|  | { | 
|  | int i; | 
|  |  | 
|  | pthread_barrier_wait (&barrier); | 
|  |  | 
|  | for (i = 0; i < NSIGS; i++) | 
|  | pthread_kill (child_thread_two, SIGUSR2); | 
|  | } | 
|  |  | 
|  | int main() | 
|  | { | 
|  | int i; | 
|  |  | 
|  | signal (SIGUSR1, handler); | 
|  | signal (SIGUSR2, handler); | 
|  |  | 
|  | pthread_barrier_init (&barrier, NULL, 3); | 
|  |  | 
|  | main_thread = pthread_self (); | 
|  | pthread_create (&child_thread, NULL, thread_function, NULL); | 
|  | pthread_create (&child_thread_two, NULL, child_two, NULL); | 
|  |  | 
|  | pthread_barrier_wait (&barrier); | 
|  |  | 
|  | for (i = 0; i < NSIGS; i++) | 
|  | pthread_kill (child_thread_two, SIGUSR1); | 
|  |  | 
|  | pthread_join (child_thread, NULL); | 
|  |  | 
|  | exit (0); | 
|  | } |