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
11volatile int g_test = 0;
12
13// A barrier to synchronize all the threads.
14pseudo_barrier_t g_barrier1;
15
16// A barrier to keep the threads from exiting until after the breakpoint has
17// been passed.
18pseudo_barrier_t g_barrier2;
19
20void *
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(rtime: 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
39void *
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
52void *
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
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

source code of lldb/test/API/functionalities/thread/break_after_join/main.cpp