110 lines · cpp
1// This test is intended to create a situation in which one thread will exit2// while a breakpoint is being handled in another thread. This may not always3// happen because it's possible that the exiting thread will exit before the4// breakpoint is hit. The test case should be flexible enough to treat that5// as success.6 7#include "pseudo_barrier.h"8#include <chrono>9#include <thread>10 11volatile int g_test = 0;12 13// A barrier to synchronize all the threads except the one that will exit.14pseudo_barrier_t g_barrier1;15 16// A barrier to synchronize all the threads including the one that will exit.17pseudo_barrier_t g_barrier2;18 19// A barrier to keep the first group of threads from exiting until after the20// breakpoint has been passed.21pseudo_barrier_t g_barrier3;22 23void *24break_thread_func ()25{26 // Wait until the entire first group of threads is running27 pseudo_barrier_wait(g_barrier1);28 29 // Wait for the exiting thread to start30 pseudo_barrier_wait(g_barrier2);31 32 // Do something33 g_test++; // Set breakpoint here34 35 // Synchronize after the breakpoint36 pseudo_barrier_wait(g_barrier3);37 38 // Return39 return NULL;40}41 42void *43wait_thread_func ()44{45 // Wait until the entire first group of threads is running46 pseudo_barrier_wait(g_barrier1);47 48 // Wait for the exiting thread to start49 pseudo_barrier_wait(g_barrier2);50 51 // Wait until the breakpoint has been passed52 pseudo_barrier_wait(g_barrier3);53 54 // Return55 return NULL;56}57 58void *59exit_thread_func ()60{61 // Sync up with the rest of the threads.62 pseudo_barrier_wait(g_barrier2);63 64 // Try to make sure this thread doesn't exit until the breakpoint is hit.65 std::this_thread::sleep_for(std::chrono::microseconds(1));66 67 // Return68 return NULL;69}70 71int main ()72{73 74 // The first barrier waits for the non-exiting threads to start.75 // This thread will also participate in that barrier.76 // The idea here is to guarantee that the exiting thread will be77 // last in the internal list maintained by the debugger.78 pseudo_barrier_init(g_barrier1, 5);79 80 // The second break synchronizes thread execution with the breakpoint.81 pseudo_barrier_init(g_barrier2, 5);82 83 // The third barrier keeps the waiting threads around until the breakpoint84 // has been passed.85 pseudo_barrier_init(g_barrier3, 4);86 87 // Create a thread to hit the breakpoint88 std::thread thread_1(break_thread_func);89 90 // Create more threads to slow the debugger down during processing.91 std::thread thread_2(wait_thread_func);92 std::thread thread_3(wait_thread_func);93 std::thread thread_4(wait_thread_func);94 95 // Wait for all these threads to get started.96 pseudo_barrier_wait(g_barrier1);97 98 // Create a thread to exit during the breakpoint99 std::thread thread_5(exit_thread_func);100 101 // Wait for the threads to finish102 thread_5.join();103 thread_4.join();104 thread_3.join();105 thread_2.join();106 thread_1.join();107 108 return 0;109}110