// LLDB C++ API Test: Verify that when the Debugger stdin
// is set to a FILE *, lldb can still successfully run a
// python command in a stop hook.

#include <errno.h>
#include <mutex>
#include <stdio.h>
#include <string>
#include <vector>

%include_SB_APIs%

#include "common.h"

#if !defined(PATH_MAX)
#define PATH_MAX 4096
#endif

using namespace lldb;

void test(SBDebugger &dbg, std::vector<std::string> args) {
  // The problem we had was that when the thread that was
  // waiting on input went into the call to 'read' it had
  // the file handle lock.  Then when the python interpreter
  // Initialized itself to run the python command, it tried
  // to flush the file channel, and that deadlocked.
  // This only happens when Async is true, since otherwise
  // the process event is handled on the I/O read thread,
  // which sidestepped the problem.
  dbg.SetAsync(true);

  SBTarget target = dbg.CreateTarget(args.at(0).c_str());
  if (!target.IsValid())
    throw Exception("invalid target");

  SBBreakpoint breakpoint = target.BreakpointCreateByName("next");
  if (!breakpoint.IsValid())
    throw Exception("invalid breakpoint");

  SBCommandInterpreter interp = dbg.GetCommandInterpreter();
  SBCommandReturnObject result;

  // Bring in the python command. We actually add two commands,
  // one that runs in the stop hook and sets a variable when it
  // runs, and one that reports out the variable so we can ensure
  // that we did indeed run the stop hook.
  const char *source_dir = "%SOURCE_DIR%";
  SBFileSpec script_spec(source_dir);
  script_spec.AppendPathComponent("some_cmd.py");
  char path[PATH_MAX];
  script_spec.GetPath(path, PATH_MAX);

  std::string import_command("command script import ");
  import_command.append(path);
  interp.HandleCommand(import_command.c_str(), result);
  if (!result.Succeeded())
    throw Exception("Couldn't import %SOURCE_DIR%/some_cmd.py");

  SBProcess process = target.LaunchSimple(nullptr, nullptr, nullptr);
  if (!process.IsValid())
    throw Exception("Couldn't launch process.");
  if (process.GetState() != lldb::eStateStopped)
    throw Exception("Process was not stopped");

  process.SetSelectedThreadByIndexID(0);

  // Now add the stop hook:
  interp.HandleCommand("target stop-hook add -o some-cmd", result);
  if (!result.Succeeded())
    throw Exception("Couldn't add a stop hook.");

  // Now switch the I/O over to a pipe, which will be handled by the
  // NativeFile class:
  int to_lldb_des[2];
  int pipe_result = pipe(to_lldb_des);
  FILE *fh_lldb_in = fdopen(to_lldb_des[0], "r");
  FILE *fh_to_lldb = fdopen(to_lldb_des[1], "w");

  // We need to reset the handle before destroying the debugger
  // or the same deadlock will stall exiting:
  class Cleanup {
  public:
    Cleanup(SBDebugger dbg, int filedes[2]) : m_dbg(dbg) {
      m_file = m_dbg.GetInputFileHandle();
      m_filedes[0] = filedes[0];
      m_filedes[1] = filedes[1];
    }
    ~Cleanup() {
      m_dbg.SetInputFileHandle(m_file, false);
      close(m_filedes[0]);
      close(m_filedes[1]);
    }

  private:
    FILE *m_file;
    SBDebugger m_dbg;
    int m_filedes[2];
  };
  Cleanup cleanup(dbg, to_lldb_des);

  dbg.SetInputFileHandle(fh_lldb_in, false);

  // Now run the command interpreter.  You have to pass true to
  // start thread so we will run the I/O in a separate thread.
  dbg.RunCommandInterpreter(false, true);

  // Now issue a stepi, and fetch the running and stopped events:
  fprintf(fh_to_lldb, "thread step-inst\n");

  SBEvent proc_event;
  StateType state;
  bool got_event;

  got_event = dbg.GetListener().WaitForEventForBroadcaster(
      100, process.GetBroadcaster(), proc_event);
  if (!got_event)
    throw Exception("Didn't get running event");
  state = SBProcess::GetStateFromEvent(proc_event);
  if (state != eStateRunning)
    throw Exception("Event wasn't a running event.");

  got_event = dbg.GetListener().WaitForEventForBroadcaster(
      100, process.GetBroadcaster(), proc_event);
  if (!got_event)
    throw Exception("Didn't get a stopped event");
  state = SBProcess::GetStateFromEvent(proc_event);
  if (state != eStateStopped)
    throw Exception("Event wasn't a stop event.");

  // At this point the stop hook should have run.  Check that:
  interp.HandleCommand("report-cmd", result);
  if (!result.Succeeded())
    throw Exception("Didn't actually call stop hook.");
}
