1 // This test is intended to create a situation in which one thread will exit 2 // while a breakpoint is being handled in another thread. This may not always 3 // happen because it's possible that the exiting thread will exit before the 4 // breakpoint is hit. The test case should be flexible enough to treat that 5 // as success. 6 7 #include "pseudo_barrier.h" 8 #include <chrono> 9 #include <thread> 10 11 volatile int g_test = 0; 12 13 // A barrier to synchronize all the threads. 14 pseudo_barrier_t g_barrier1; 15 16 // A barrier to keep the threads from exiting until after the breakpoint has 17 // been passed. 18 pseudo_barrier_t g_barrier2; 19 20 void * break_thread_func()21break_thread_func () 22 { 23 // Wait until all the threads are running 24 pseudo_barrier_wait(g_barrier1); 25 26 // Wait for the join thread to join 27 std::this_thread::sleep_for(std::chrono::microseconds(50)); 28 29 // Do something 30 g_test++; // Set breakpoint here 31 32 // Synchronize after the breakpoint 33 pseudo_barrier_wait(g_barrier2); 34 35 // Return 36 return NULL; 37 } 38 39 void * wait_thread_func()40wait_thread_func () 41 { 42 // Wait until the entire first group of threads is running 43 pseudo_barrier_wait(g_barrier1); 44 45 // Wait until the breakpoint has been passed 46 pseudo_barrier_wait(g_barrier2); 47 48 // Return 49 return NULL; 50 } 51 52 void * join_thread_func(void * input)53join_thread_func (void *input) 54 { 55 std::thread *thread_to_join = (std::thread *)input; 56 57 // Sync up with the rest of the threads. 58 pseudo_barrier_wait(g_barrier1); 59 60 // Join the other thread 61 thread_to_join->join(); 62 63 // Return 64 return NULL; 65 } 66 main()67int main () 68 { 69 // The first barrier waits for the non-joining threads to start. 70 // This thread will also participate in that barrier. 71 // The idea here is to guarantee that the joining thread will be 72 // last in the internal list maintained by the debugger. 73 pseudo_barrier_init(g_barrier1, 5); 74 75 // The second barrier keeps the waiting threads around until the breakpoint 76 // has been passed. 77 pseudo_barrier_init(g_barrier2, 4); 78 79 // Create a thread to hit the breakpoint 80 std::thread thread_1(break_thread_func); 81 82 // Create more threads to slow the debugger down during processing. 83 std::thread thread_2(wait_thread_func); 84 std::thread thread_3(wait_thread_func); 85 std::thread thread_4(wait_thread_func); 86 87 // Create a thread to join the breakpoint thread 88 std::thread thread_5(join_thread_func, &thread_1); 89 90 // Wait for the threads to finish 91 thread_5.join(); // implies thread_1 is already finished 92 thread_4.join(); 93 thread_3.join(); 94 thread_2.join(); 95 96 return 0; 97 } 98