1 // This test will present lldb with two threads one of which the test will 2 // overlay with an OSPlugin thread. Then we'll do a step out on the thread_1, 3 // but arrange to hit a breakpoint in main before the step out completes. At 4 // that point we will not report an OS plugin thread for thread_1. Then we'll 5 // run again and hit the step out breakpoint. Make sure we haven't deleted 6 // that, and recognize it. 7 8 #include <condition_variable> 9 #include <mutex> 10 #include <stdio.h> 11 #include <thread> 12 13 static int g_value = 0; // I don't have access to the real threads in the 14 // OS Plugin, and I don't want to have to count 15 // StopID's. So I'm using this value to tell me which 16 // stop point the program has reached. 17 std::mutex g_mutex; 18 std::condition_variable g_cv; 19 static int g_condition = 0; // Using this as the variable backing g_cv 20 // to prevent spurious wakeups. 21 step_out_of_here()22void step_out_of_here() { 23 std::unique_lock<std::mutex> func_lock(g_mutex); 24 // Set a breakpoint:first stop in thread - do a step out. 25 g_condition = 1; 26 g_cv.notify_one(); 27 g_cv.wait(func_lock, [&] { return g_condition == 2; }); 28 } 29 thread_func()30void *thread_func() { 31 // Do something 32 step_out_of_here(); 33 34 // Return 35 return NULL; 36 } 37 main()38int main() { 39 // Lock the mutex so we can block the thread: 40 std::unique_lock<std::mutex> main_lock(g_mutex); 41 // Create the thread 42 std::thread thread_1(thread_func); 43 g_cv.wait(main_lock, [&] { return g_condition == 1; }); 44 g_value = 1; 45 g_condition = 2; 46 // Stop here and do not make a memory thread for thread_1. 47 g_cv.notify_one(); 48 g_value = 2; 49 main_lock.unlock(); 50 51 // Wait for the threads to finish 52 thread_1.join(); 53 54 return 0; 55 } 56