2 // This program creates NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS of pthreads,
3 // creates an lldb Debugger on each thread, creates targets, inserts two
4 // breakpoints, runs to the first breakpoint, backtraces, runs to the second
5 // breakpoint, backtraces, kills the inferior process, closes down the
8 // The main thread keeps track of which pthreads have completed and which
9 // pthreads have completed successfully, and exits when all pthreads have
10 // completed successfully, or our time limit has been exceeded.
12 // This test file helps to uncover race conditions and locking mistakes
13 // that are hit when lldb is being used to debug multiple processes
20 #include "lldb/API/LLDB.h"
21 #include "lldb/API/SBCommandInterpreter.h"
22 #include "lldb/API/SBCommandReturnObject.h"
23 #include "lldb/API/SBDebugger.h"
29 #define NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS 10
35 bool *completed_threads_array
= 0;
36 bool *successful_threads_array
= 0;
38 const char *inferior_process_name
= "testprog";
41 wait_for_stop_event (SBProcess process
, SBListener listener
)
47 bool waitfor_ret
= listener
.WaitForEvent (2, event
);
48 if (event
.GetType() == SBProcess::eBroadcastBitStateChanged
)
50 if (process
.GetState() == StateType::eStateStopped
51 || process
.GetState() == StateType::eStateCrashed
52 || process
.GetState() == StateType::eStateDetached
53 || process
.GetState() == StateType::eStateExited
)
63 walk_stack_to_main (SBThread thread
)
65 if (thread
.IsValid() == 0)
70 bool found_main
= false;
71 uint32_t curr_frame
= 0;
72 const uint32_t framecount
= thread
.GetNumFrames();
73 while (!found_main
&& curr_frame
< framecount
)
75 SBFrame frame
= thread
.GetFrameAtIndex (curr_frame
);
76 if (strcmp (frame
.GetFunctionName(), "main") == 0)
86 void *do_one_debugger (void *in
)
88 uint64_t threadnum
= (uint64_t) in
;
90 #if defined (__APPLE__)
92 asprintf (&threadname
, "thread #%lld", threadnum
);
93 pthread_setname_np (threadname
);
98 printf ("#%lld: Starting debug session\n", threadnum
);
101 SBDebugger debugger
= lldb::SBDebugger::Create (false);
102 if (debugger
.IsValid ())
104 debugger
.SetAsync (true);
105 SBTarget target
= debugger
.CreateTargetWithFileAndArch(inferior_process_name
, "x86_64");
106 SBCommandInterpreter command_interp
= debugger
.GetCommandInterpreter();
107 if (target
.IsValid())
109 SBBreakpoint bar_br
= target
.BreakpointCreateByName ("bar", "testprog");
110 if (!bar_br
.IsValid())
112 printf ("#%lld: failed to set breakpoint on bar, exiting.\n", threadnum
);
115 SBBreakpoint foo_br
= target
.BreakpointCreateByName ("foo", "testprog");
116 if (!foo_br
.IsValid())
118 printf ("#%lld: Failed to set breakpoint on foo()\n", threadnum
);
121 SBLaunchInfo
launch_info (NULL
);
123 SBProcess process
= target
.Launch (launch_info
, error
);
124 if (process
.IsValid())
126 SBListener listener
= debugger
.GetListener();
127 SBBroadcaster broadcaster
= process
.GetBroadcaster();
128 uint32_t rc
= broadcaster
.AddListener (listener
, SBProcess::eBroadcastBitStateChanged
);
131 printf ("adding listener failed\n");
135 wait_for_stop_event (process
, listener
);
137 if (!walk_stack_to_main (process
.GetThreadAtIndex(0)))
139 printf ("#%lld: backtrace while @ foo() failed\n", threadnum
);
140 completed_threads_array
[threadnum
] = true;
144 if (strcmp (process
.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName(), "foo") != 0)
147 printf ("#%lld: First breakpoint did not stop at foo(), instead stopped at '%s'\n", threadnum
, process
.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName());
149 completed_threads_array
[threadnum
] = true;
155 wait_for_stop_event (process
, listener
);
157 if (process
.GetState() == StateType::eStateExited
)
159 printf ("#%lld: Process exited\n", threadnum
);
160 completed_threads_array
[threadnum
] = true;
165 if (!walk_stack_to_main (process
.GetThreadAtIndex(0)))
167 printf ("#%lld: backtrace while @ bar() failed\n", threadnum
);
168 completed_threads_array
[threadnum
] = true;
172 if (strcmp (process
.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName(), "bar") != 0)
174 printf ("#%lld: First breakpoint did not stop at bar()\n", threadnum
);
175 completed_threads_array
[threadnum
] = true;
181 wait_for_stop_event (process
, listener
);
183 SBDebugger::Destroy(debugger
);
186 printf ("#%lld: All good!\n", threadnum
);
188 successful_threads_array
[threadnum
] = true;
189 completed_threads_array
[threadnum
] = true;
194 printf("#%lld: process failed to launch\n", threadnum
);
195 successful_threads_array
[threadnum
] = false;
196 completed_threads_array
[threadnum
] = true;
202 printf ("#%lld: did not get valid target\n", threadnum
);
203 successful_threads_array
[threadnum
] = false;
204 completed_threads_array
[threadnum
] = true;
210 printf ("#%lld: did not get debugger\n", threadnum
);
211 successful_threads_array
[threadnum
] = false;
212 completed_threads_array
[threadnum
] = true;
215 completed_threads_array
[threadnum
] = true;
219 int main (int argc
, char **argv
)
221 #if !defined(_MSC_VER)
222 signal(SIGPIPE
, SIG_IGN
);
225 SBDebugger::Initialize();
227 completed_threads_array
= (bool *) malloc (sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS
);
228 memset (completed_threads_array
, 0, sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS
);
229 successful_threads_array
= (bool *) malloc (sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS
);
230 memset (successful_threads_array
, 0, sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS
);
232 if (argc
> 1 && argv
[1] != NULL
)
234 inferior_process_name
= argv
[1];
237 std::thread threads
[NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS
];
238 for (uint64_t i
= 0; i
< NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS
; i
++)
240 threads
[i
] = std::move(std::thread(do_one_debugger
, (void*)i
));
244 int max_time_to_wait
= 20; // 20 iterations, or 60 seconds
248 std::this_thread::sleep_for(std::chrono::seconds(3));
249 bool all_done
= true;
250 int successful_threads
= 0;
251 int total_completed_threads
= 0;
252 for (uint64_t i
= 0; i
< NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS
; i
++)
254 if (successful_threads_array
[i
] == true)
255 successful_threads
++;
256 if (completed_threads_array
[i
] == true)
257 total_completed_threads
++;
258 if (completed_threads_array
[i
] == false)
266 printf ("All threads completed.\n");
267 printf ("%d threads completed successfully out of %d\n", successful_threads
, NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS
);
269 SBDebugger::Terminate();
275 printf ("%d threads completed so far (%d successfully), out of %d\n", total_completed_threads
, successful_threads
, NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS
);
278 if (iter
++ == max_time_to_wait
)
280 printf ("reached maximum timeout but only %d threads have completed so far (%d successfully), out of %d. Exiting.\n", total_completed_threads
, successful_threads
, NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS
);
286 SBDebugger::Terminate();