1// LLDB test snippet that registers a listener with a process that hits
2// a breakpoint.
3
4#include <atomic>
5#include <iostream>
6#include <string>
7#include <thread>
8#include <vector>
9
10#include "lldb-headers.h"
11#include "common.h"
12
13using namespace lldb;
14using namespace std;
15
16void listener_func();
17void check_listener(SBDebugger &dbg);
18
19// Listener thread and related variables
20atomic<bool> g_done;
21SBListener g_listener("test-listener");
22thread g_listener_thread;
23
24void shutdown_listener() {
25  g_done.store(true);
26  if (g_listener_thread.joinable())
27    g_listener_thread.join();
28}
29
30void test(SBDebugger &dbg, std::vector<string> args) {
31  try {
32    g_done.store(false);
33    SBTarget target = dbg.CreateTarget(args.at(0).c_str());
34    if (!target.IsValid()) throw Exception("invalid target");
35
36    SBBreakpoint breakpoint = target.BreakpointCreateByName("next");
37    if (!breakpoint.IsValid()) throw Exception("invalid breakpoint");
38
39    std::unique_ptr<char> working_dir(get_working_dir());
40
41    SBError error;
42    SBProcess process = target.Launch(g_listener,
43                                      0, 0, 0, 0, 0,
44                                      working_dir.get(),
45                                      0,
46                                      false,
47                                      error);
48    if (!error.Success())
49      throw Exception("Error launching process.");
50
51    /* FIXME: the approach below deadlocks
52    SBProcess process = target.LaunchSimple(0, 0, working_dir.get());
53
54    // get debugger listener (which is attached to process by default)
55    g_listener = dbg.GetListener();
56    */
57
58    // FIXME: because a listener is attached to the process at launch-time,
59    // registering the listener below results in two listeners being attached,
60    // which is not supported by LLDB.
61    // register listener
62    // process.GetBroadcaster().AddListener(g_listener,
63    //                                   SBProcess::eBroadcastBitStateChanged);
64
65    // start listener thread
66    g_listener_thread = thread(listener_func);
67    check_listener(dbg);
68
69  } catch (Exception &e) {
70    shutdown_listener();
71    throw e;
72  }
73  shutdown_listener();
74}
75