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
13static 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.
17std::mutex g_mutex;
18std::condition_variable g_cv;
19static int g_condition = 0; // Using this as the variable backing g_cv
20 // to prevent spurious wakeups.
21
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(lock&: func_lock, p: [&] { return g_condition == 2; });
28}
29
30void *thread_func() {
31 // Do something
32 step_out_of_here();
33
34 // Return
35 return NULL;
36}
37
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(lock&: main_lock, p: [&] { 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

source code of lldb/test/API/functionalities/plugins/python_os_plugin/stepping_plugin_threads/main.cpp