xref: /llvm-project/lldb/test/API/functionalities/thread/break_after_join/main.cpp (revision fdea9a4ec9b0d9585b8fe8a612686d9f44f40ddc)
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()21 break_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()40 wait_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)53 join_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()67 int 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