1 | // This test is intended to create a situation in which one thread will exit |
2 | // while the debugger is stepping in another thread. |
3 | |
4 | #include "pseudo_barrier.h" |
5 | #include <thread> |
6 | |
7 | #define do_nothing() |
8 | |
9 | // A barrier to synchronize thread start. |
10 | pseudo_barrier_t g_barrier; |
11 | |
12 | volatile int g_thread_exited = 0; |
13 | |
14 | volatile int g_test = 0; |
15 | |
16 | void * |
17 | step_thread_func () |
18 | { |
19 | // Wait until both threads are started. |
20 | pseudo_barrier_wait(g_barrier); |
21 | |
22 | g_test = 0; // Set breakpoint here |
23 | |
24 | while (!g_thread_exited) |
25 | g_test++; |
26 | |
27 | // One more time to provide a continue point |
28 | g_test++; // Continue from here |
29 | |
30 | // Return |
31 | return NULL; |
32 | } |
33 | |
34 | void * |
35 | exit_thread_func () |
36 | { |
37 | // Wait until both threads are started. |
38 | pseudo_barrier_wait(g_barrier); |
39 | |
40 | // Wait until the other thread is stepping. |
41 | while (g_test == 0) |
42 | do_nothing(); |
43 | |
44 | // Return |
45 | return NULL; |
46 | } |
47 | |
48 | int main () |
49 | { |
50 | // Synchronize thread start so that doesn't happen during stepping. |
51 | pseudo_barrier_init(g_barrier, 2); |
52 | |
53 | // Create a thread to hit the breakpoint. |
54 | std::thread thread_1(step_thread_func); |
55 | |
56 | // Create a thread to exit while we're stepping. |
57 | std::thread thread_2(exit_thread_func); |
58 | |
59 | // Wait for the exit thread to finish. |
60 | thread_2.join(); |
61 | |
62 | // Let the stepping thread know the other thread is gone. |
63 | g_thread_exited = 1; |
64 | |
65 | // Wait for the stepping thread to finish. |
66 | thread_1.join(); |
67 | |
68 | return 0; |
69 | } |
70 | |