brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.3 KiB · 393e717 Raw
135 lines · plain
1// LLDB C++ API Test: Verify that when the Debugger stdin2// is set to a FILE *, lldb can still successfully run a3// python command in a stop hook.4 5#include <errno.h>6#include <mutex>7#include <stdio.h>8#include <string>9#include <vector>10 11%include_SB_APIs%12 13#include "common.h"14 15#if !defined(PATH_MAX)16#define PATH_MAX 409617#endif18 19using namespace lldb;20 21void test(SBDebugger &dbg, std::vector<std::string> args) {22  // The problem we had was that when the thread that was23  // waiting on input went into the call to 'read' it had24  // the file handle lock.  Then when the python interpreter25  // Initialized itself to run the python command, it tried26  // to flush the file channel, and that deadlocked.27  // This only happens when Async is true, since otherwise28  // the process event is handled on the I/O read thread,29  // which sidestepped the problem.30  dbg.SetAsync(true);31 32  SBTarget target = dbg.CreateTarget(args.at(0).c_str());33  if (!target.IsValid())34    throw Exception("invalid target");35 36  SBBreakpoint breakpoint = target.BreakpointCreateByName("next");37  if (!breakpoint.IsValid())38    throw Exception("invalid breakpoint");39 40  SBCommandInterpreter interp = dbg.GetCommandInterpreter();41  SBCommandReturnObject result;42 43  // Bring in the python command. We actually add two commands,44  // one that runs in the stop hook and sets a variable when it45  // runs, and one that reports out the variable so we can ensure46  // 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);52 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");58 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");64 65  process.SetSelectedThreadByIndexID(0);66 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.");71 72  // Now switch the I/O over to a pipe, which will be handled by the73  // 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");78 79  // We need to reset the handle before destroying the debugger80  // 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    }93 94  private:95    FILE *m_file;96    SBDebugger m_dbg;97    int m_filedes[2];98  };99  Cleanup cleanup(dbg, to_lldb_des);100 101  dbg.SetInputFileHandle(fh_lldb_in, false);102 103  // Now run the command interpreter.  You have to pass true to104  // start thread so we will run the I/O in a separate thread.105  dbg.RunCommandInterpreter(false, true);106 107  // Now issue a stepi, and fetch the running and stopped events:108  fprintf(fh_to_lldb, "thread step-inst\n");109 110  SBEvent proc_event;111  StateType state;112  bool got_event;113 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.");121 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.");129 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.");134}135