1 | // This test is intended to create a situation in which multiple events |
2 | // (breakpoints, watchpoints, crashes, and signal generation/delivery) happen |
3 | // from multiple threads. The test expects the debugger to set a breakpoint on |
4 | // the main thread (before any worker threads are spawned) and modify variables |
5 | // which control the number of threads that are spawned for each action. |
6 | |
7 | #include "pseudo_barrier.h" |
8 | #include <vector> |
9 | |
10 | #include <pthread.h> |
11 | |
12 | #include <signal.h> |
13 | #include <sys/types.h> |
14 | #include <unistd.h> |
15 | |
16 | typedef std::vector<std::pair<unsigned, void*(*)(void*)> > action_counts; |
17 | typedef std::vector<pthread_t> thread_vector; |
18 | |
19 | pseudo_barrier_t g_barrier; |
20 | int g_breakpoint = 0; |
21 | int g_sigusr1_count = 0; |
22 | uint32_t g_watchme; |
23 | |
24 | struct action_args { |
25 | int delay; |
26 | }; |
27 | |
28 | // Perform any extra actions required by thread 'input' arg |
29 | void do_action_args(void *input) { |
30 | if (input) { |
31 | action_args *args = static_cast<action_args*>(input); |
32 | sleep(seconds: args->delay); |
33 | } |
34 | } |
35 | |
36 | void * |
37 | breakpoint_func (void *input) |
38 | { |
39 | // Wait until all threads are running |
40 | pseudo_barrier_wait(g_barrier); |
41 | do_action_args(input); |
42 | |
43 | // Do something |
44 | g_breakpoint++; // Set breakpoint here |
45 | return 0; |
46 | } |
47 | |
48 | void * |
49 | signal_func (void *input) { |
50 | // Wait until all threads are running |
51 | pseudo_barrier_wait(g_barrier); |
52 | do_action_args(input); |
53 | |
54 | // Send a user-defined signal to the current process |
55 | //kill(getpid(), SIGUSR1); |
56 | // Send a user-defined signal to the current thread |
57 | pthread_kill(threadid: pthread_self(), SIGUSR1); |
58 | |
59 | return 0; |
60 | } |
61 | |
62 | void * |
63 | watchpoint_func (void *input) { |
64 | pseudo_barrier_wait(g_barrier); |
65 | do_action_args(input); |
66 | |
67 | g_watchme = 1; // watchpoint triggers here |
68 | return 0; |
69 | } |
70 | |
71 | void * |
72 | crash_func (void *input) { |
73 | pseudo_barrier_wait(g_barrier); |
74 | do_action_args(input); |
75 | |
76 | int *a = 0; |
77 | *a = 5; // crash happens here |
78 | return 0; |
79 | } |
80 | |
81 | void sigusr1_handler(int sig) { |
82 | if (sig == SIGUSR1) |
83 | g_sigusr1_count += 1; // Break here in signal handler |
84 | } |
85 | |
86 | /// Register a simple function for to handle signal |
87 | void register_signal_handler(int signal, void (*handler)(int)) |
88 | { |
89 | sigset_t empty_sigset; |
90 | sigemptyset(set: &empty_sigset); |
91 | |
92 | struct sigaction action; |
93 | action.sa_sigaction = 0; |
94 | action.sa_mask = empty_sigset; |
95 | action.sa_flags = 0; |
96 | action.sa_handler = handler; |
97 | sigaction(SIGUSR1, act: &action, oact: 0); |
98 | } |
99 | |
100 | void start_threads(thread_vector& threads, |
101 | action_counts& actions, |
102 | void* args = 0) { |
103 | action_counts::iterator b = actions.begin(), e = actions.end(); |
104 | for(action_counts::iterator i = b; i != e; ++i) { |
105 | for(unsigned count = 0; count < i->first; ++count) { |
106 | pthread_t t; |
107 | pthread_create(newthread: &t, attr: 0, start_routine: i->second, arg: args); |
108 | threads.push_back(x: t); |
109 | } |
110 | } |
111 | } |
112 | |
113 | int dotest() |
114 | { |
115 | g_watchme = 0; |
116 | |
117 | // Actions are triggered immediately after the thread is spawned |
118 | unsigned num_breakpoint_threads = 1; |
119 | unsigned num_watchpoint_threads = 0; |
120 | unsigned num_signal_threads = 1; |
121 | unsigned num_crash_threads = 0; |
122 | |
123 | // Actions below are triggered after a 1-second delay |
124 | unsigned num_delay_breakpoint_threads = 0; |
125 | unsigned num_delay_watchpoint_threads = 0; |
126 | unsigned num_delay_signal_threads = 0; |
127 | unsigned num_delay_crash_threads = 0; |
128 | |
129 | register_signal_handler(SIGUSR1, handler: sigusr1_handler); // Break here and adjust num_[breakpoint|watchpoint|signal|crash]_threads |
130 | |
131 | unsigned total_threads = num_breakpoint_threads \ |
132 | + num_watchpoint_threads \ |
133 | + num_signal_threads \ |
134 | + num_crash_threads \ |
135 | + num_delay_breakpoint_threads \ |
136 | + num_delay_watchpoint_threads \ |
137 | + num_delay_signal_threads \ |
138 | + num_delay_crash_threads; |
139 | |
140 | // Don't let either thread do anything until they're both ready. |
141 | pseudo_barrier_init(g_barrier, total_threads); |
142 | |
143 | action_counts actions; |
144 | actions.push_back(x: std::make_pair(x&: num_breakpoint_threads, y&: breakpoint_func)); |
145 | actions.push_back(x: std::make_pair(x&: num_watchpoint_threads, y&: watchpoint_func)); |
146 | actions.push_back(x: std::make_pair(x&: num_signal_threads, y&: signal_func)); |
147 | actions.push_back(x: std::make_pair(x&: num_crash_threads, y&: crash_func)); |
148 | |
149 | action_counts delay_actions; |
150 | delay_actions.push_back(x: std::make_pair(x&: num_delay_breakpoint_threads, y&: breakpoint_func)); |
151 | delay_actions.push_back(x: std::make_pair(x&: num_delay_watchpoint_threads, y&: watchpoint_func)); |
152 | delay_actions.push_back(x: std::make_pair(x&: num_delay_signal_threads, y&: signal_func)); |
153 | delay_actions.push_back(x: std::make_pair(x&: num_delay_crash_threads, y&: crash_func)); |
154 | |
155 | // Create threads that handle instant actions |
156 | thread_vector threads; |
157 | start_threads(threads, actions); |
158 | |
159 | // Create threads that handle delayed actions |
160 | action_args delay_arg; |
161 | delay_arg.delay = 1; |
162 | start_threads(threads, actions&: delay_actions, args: &delay_arg); |
163 | |
164 | // Join all threads |
165 | typedef std::vector<pthread_t>::iterator thread_iterator; |
166 | for(thread_iterator t = threads.begin(); t != threads.end(); ++t) |
167 | pthread_join(th: *t, thread_return: 0); |
168 | |
169 | return 0; |
170 | } |
171 | |
172 | int main () |
173 | { |
174 | dotest(); |
175 | return 0; // Break here and verify one thread is active. |
176 | } |
177 | |
178 | |
179 | |