Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / test / API / api / multithreaded / test_stop-hook.cpp.template
blob393e717cceb5a5c58ecc1a4eeb6865ab44c15ac0
1 // LLDB C++ API Test: Verify that when the Debugger stdin
2 // is set to a FILE *, lldb can still successfully run a
3 // python command in a stop hook.
5 #include <errno.h>
6 #include <mutex>
7 #include <stdio.h>
8 #include <string>
9 #include <vector>
11 %include_SB_APIs%
13 #include "common.h"
15 #if !defined(PATH_MAX)
16 #define PATH_MAX 4096
17 #endif
19 using namespace lldb;
21 void test(SBDebugger &dbg, std::vector<std::string> args) {
22   // The problem we had was that when the thread that was
23   // waiting on input went into the call to 'read' it had
24   // the file handle lock.  Then when the python interpreter
25   // Initialized itself to run the python command, it tried
26   // to flush the file channel, and that deadlocked.
27   // This only happens when Async is true, since otherwise
28   // the process event is handled on the I/O read thread,
29   // which sidestepped the problem.
30   dbg.SetAsync(true);
32   SBTarget target = dbg.CreateTarget(args.at(0).c_str());
33   if (!target.IsValid())
34     throw Exception("invalid target");
36   SBBreakpoint breakpoint = target.BreakpointCreateByName("next");
37   if (!breakpoint.IsValid())
38     throw Exception("invalid breakpoint");
40   SBCommandInterpreter interp = dbg.GetCommandInterpreter();
41   SBCommandReturnObject result;
43   // Bring in the python command. We actually add two commands,
44   // one that runs in the stop hook and sets a variable when it
45   // runs, and one that reports out the variable so we can ensure
46   // that we did indeed run the stop hook.
47   const char *source_dir = "%SOURCE_DIR%";
48   SBFileSpec script_spec(source_dir);
49   script_spec.AppendPathComponent("some_cmd.py");
50   char path[PATH_MAX];
51   script_spec.GetPath(path, PATH_MAX);
53   std::string import_command("command script import ");
54   import_command.append(path);
55   interp.HandleCommand(import_command.c_str(), result);
56   if (!result.Succeeded())
57     throw Exception("Couldn't import %SOURCE_DIR%/some_cmd.py");
59   SBProcess process = target.LaunchSimple(nullptr, nullptr, nullptr);
60   if (!process.IsValid())
61     throw Exception("Couldn't launch process.");
62   if (process.GetState() != lldb::eStateStopped)
63     throw Exception("Process was not stopped");
65   process.SetSelectedThreadByIndexID(0);
67   // Now add the stop hook:
68   interp.HandleCommand("target stop-hook add -o some-cmd", result);
69   if (!result.Succeeded())
70     throw Exception("Couldn't add a stop hook.");
72   // Now switch the I/O over to a pipe, which will be handled by the
73   // NativeFile class:
74   int to_lldb_des[2];
75   int pipe_result = pipe(to_lldb_des);
76   FILE *fh_lldb_in = fdopen(to_lldb_des[0], "r");
77   FILE *fh_to_lldb = fdopen(to_lldb_des[1], "w");
79   // We need to reset the handle before destroying the debugger
80   // or the same deadlock will stall exiting:
81   class Cleanup {
82   public:
83     Cleanup(SBDebugger dbg, int filedes[2]) : m_dbg(dbg) {
84       m_file = m_dbg.GetInputFileHandle();
85       m_filedes[0] = filedes[0];
86       m_filedes[1] = filedes[1];
87     }
88     ~Cleanup() {
89       m_dbg.SetInputFileHandle(m_file, false);
90       close(m_filedes[0]);
91       close(m_filedes[1]);
92     }
94   private:
95     FILE *m_file;
96     SBDebugger m_dbg;
97     int m_filedes[2];
98   };
99   Cleanup cleanup(dbg, to_lldb_des);
101   dbg.SetInputFileHandle(fh_lldb_in, false);
103   // Now run the command interpreter.  You have to pass true to
104   // start thread so we will run the I/O in a separate thread.
105   dbg.RunCommandInterpreter(false, true);
107   // Now issue a stepi, and fetch the running and stopped events:
108   fprintf(fh_to_lldb, "thread step-inst\n");
110   SBEvent proc_event;
111   StateType state;
112   bool got_event;
114   got_event = dbg.GetListener().WaitForEventForBroadcaster(
115       100, process.GetBroadcaster(), proc_event);
116   if (!got_event)
117     throw Exception("Didn't get running event");
118   state = SBProcess::GetStateFromEvent(proc_event);
119   if (state != eStateRunning)
120     throw Exception("Event wasn't a running event.");
122   got_event = dbg.GetListener().WaitForEventForBroadcaster(
123       100, process.GetBroadcaster(), proc_event);
124   if (!got_event)
125     throw Exception("Didn't get a stopped event");
126   state = SBProcess::GetStateFromEvent(proc_event);
127   if (state != eStateStopped)
128     throw Exception("Event wasn't a stop event.");
130   // At this point the stop hook should have run.  Check that:
131   interp.HandleCommand("report-cmd", result);
132   if (!result.Succeeded())
133     throw Exception("Didn't actually call stop hook.");