Index: lldb/include/lldb/API/SBCommandInterpreterRunOptions.h =================================================================== --- lldb/include/lldb/API/SBCommandInterpreterRunOptions.h +++ lldb/include/lldb/API/SBCommandInterpreterRunOptions.h @@ -69,6 +69,29 @@ m_opaque_up; }; +class LLDB_API SBCommandInterpreterRunResults { + friend class SBDebugger; + friend class SBCommandInterpreter; + +public: + SBCommandInterpreterRunResults(); + ~SBCommandInterpreterRunResults() = default; + + int GetNumberOfErrors() const; + bool GetQuitRequested() const; + bool GetStoppedForCrash() const; + +protected: + void SetNumberOfErrors(int); + void SetQuitRequested(bool); + void SetStoppedForCrash(bool); + +private: + int m_num_errors; + bool m_quit_requested; + bool m_stopped_for_crash; +}; + } // namespace lldb #endif // LLDB_API_SBCOMMANDINTERPRETERRUNOPTIONS_H Index: lldb/include/lldb/API/SBDebugger.h =================================================================== --- lldb/include/lldb/API/SBDebugger.h +++ lldb/include/lldb/API/SBDebugger.h @@ -297,6 +297,9 @@ int &num_errors, bool &quit_requested, bool &stopped_for_crash); + SBCommandInterpreterRunResults + RunCommandInterpreter(const SBCommandInterpreterRunOptions &options); + SBError RunREPL(lldb::LanguageType language, const char *repl_options); private: Index: lldb/include/lldb/API/SBDefines.h =================================================================== --- lldb/include/lldb/API/SBDefines.h +++ lldb/include/lldb/API/SBDefines.h @@ -28,6 +28,7 @@ class LLDB_API SBCommand; class LLDB_API SBCommandInterpreter; class LLDB_API SBCommandInterpreterRunOptions; +class LLDB_API SBCommandInterpreterRunResults; class LLDB_API SBCommandPluginInterface; class LLDB_API SBCommandReturnObject; class LLDB_API SBCommunication; Index: lldb/source/API/SBCommandInterpreterRunOptions.cpp =================================================================== --- lldb/source/API/SBCommandInterpreterRunOptions.cpp +++ lldb/source/API/SBCommandInterpreterRunOptions.cpp @@ -163,6 +163,44 @@ return *m_opaque_up; } +SBCommandInterpreterRunResults::SBCommandInterpreterRunResults() + : m_num_errors(0), m_quit_requested(false), m_stopped_for_crash(false) { + LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCommandInterpreterRunResults); +} + +int SBCommandInterpreterRunResults::GetNumberOfErrors() const { + LLDB_RECORD_METHOD_CONST_NO_ARGS(int, SBCommandInterpreterRunResults, + GetNumberOfErrors); + + return m_num_errors; +} + +bool SBCommandInterpreterRunResults::GetQuitRequested() const { + LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreterRunResults, + GetQuitRequested); + + return m_quit_requested; +} + +bool SBCommandInterpreterRunResults::GetStoppedForCrash() const { + LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreterRunResults, + GetStoppedForCrash); + + return m_stopped_for_crash; +} + +void SBCommandInterpreterRunResults::SetNumberOfErrors(int num_errors) { + m_num_errors = num_errors; +} + +void SBCommandInterpreterRunResults::SetQuitRequested(bool quit_requested) { + m_quit_requested = quit_requested; +} +void SBCommandInterpreterRunResults::SetStoppedForCrash( + bool stopped_for_crash) { + m_stopped_for_crash = stopped_for_crash; +} + namespace lldb_private { namespace repro { @@ -204,6 +242,13 @@ GetSpawnThread, ()); LLDB_REGISTER_METHOD(void, SBCommandInterpreterRunOptions, SetSpawnThread, (bool)); + LLDB_REGISTER_CONSTRUCTOR(SBCommandInterpreterRunResults, ()); + LLDB_REGISTER_METHOD_CONST(int, SBCommandInterpreterRunResults, + GetNumberOfErrors, ()); + LLDB_REGISTER_METHOD_CONST(bool, SBCommandInterpreterRunResults, + GetQuitRequested, ()); + LLDB_REGISTER_METHOD_CONST(bool, SBCommandInterpreterRunResults, + GetStoppedForCrash, ()); } } // namespace repro Index: lldb/source/API/SBDebugger.cpp =================================================================== --- lldb/source/API/SBDebugger.cpp +++ lldb/source/API/SBDebugger.cpp @@ -1197,6 +1197,22 @@ } } +SBCommandInterpreterRunResults SBDebugger::RunCommandInterpreter( + const SBCommandInterpreterRunOptions &options) { + if (!m_opaque_sp) + return {}; + + CommandInterpreter &interp = m_opaque_sp->GetCommandInterpreter(); + interp.RunCommandInterpreter(options.ref()); + + SBCommandInterpreterRunResults results; + results.SetNumberOfErrors(interp.GetNumErrors()); + results.SetQuitRequested(interp.GetQuitRequested()); + results.SetStoppedForCrash(interp.GetStoppedForCrash()); + + return results; +} + SBError SBDebugger::RunREPL(lldb::LanguageType language, const char *repl_options) { LLDB_RECORD_METHOD(lldb::SBError, SBDebugger, RunREPL, Index: lldb/tools/driver/Driver.cpp =================================================================== --- lldb/tools/driver/Driver.cpp +++ lldb/tools/driver/Driver.cpp @@ -588,10 +588,7 @@ const char *commands_data = commands_stream.GetData(); const size_t commands_size = commands_stream.GetSize(); - // The command file might have requested that we quit, this variable will - // track that. - bool quit_requested = false; - bool stopped_for_crash = false; + bool go_interactive = true; if ((commands_data != nullptr) && (commands_size != 0u)) { FILE *commands_file = PrepareCommandsForSourcing(commands_data, commands_size); @@ -603,23 +600,25 @@ m_debugger.SetInputFileHandle(commands_file, true); - // Set the debugger into Sync mode when running the command file. - // Otherwise command files - // that run the target won't run in a sensible way. + // Set the debugger into Sync mode when running the command file. Otherwise + // command files that run the target won't run in a sensible way. bool old_async = m_debugger.GetAsync(); m_debugger.SetAsync(false); - int num_errors = 0; SBCommandInterpreterRunOptions options; + options.SetAutoHandleEvents(true); + options.SetSpawnThread(false); options.SetStopOnError(true); - if (m_option_data.m_batch) - options.SetStopOnCrash(true); + options.SetStopOnCrash(m_option_data.m_batch); - m_debugger.RunCommandInterpreter(handle_events, spawn_thread, options, - num_errors, quit_requested, - stopped_for_crash); + SBCommandInterpreterRunResults results = + m_debugger.RunCommandInterpreter(options); + if (results.GetQuitRequested()) + go_interactive = false; + if (m_option_data.m_batch && !results.GetStoppedForCrash()) + go_interactive = false; - if (m_option_data.m_batch && stopped_for_crash && + if (m_option_data.m_batch && results.GetStoppedForCrash() && !m_option_data.m_after_crash_commands.empty()) { SBStream crash_commands_stream; WriteCommandsForSourcing(eCommandPlacementAfterCrash, @@ -629,30 +628,19 @@ commands_file = PrepareCommandsForSourcing(crash_commands_data, crash_commands_size); if (commands_file != nullptr) { - bool local_quit_requested; - bool local_stopped_for_crash; m_debugger.SetInputFileHandle(commands_file, true); - - m_debugger.RunCommandInterpreter(handle_events, spawn_thread, options, - num_errors, local_quit_requested, - local_stopped_for_crash); - if (local_quit_requested) - quit_requested = true; + SBCommandInterpreterRunResults local_results = + m_debugger.RunCommandInterpreter(options); + if (local_results.GetQuitRequested()) + go_interactive = false; } } m_debugger.SetAsync(old_async); } - // Now set the input file handle to STDIN and run the command - // interpreter again in interactive mode or repl mode and let the debugger - // take ownership of stdin - - bool go_interactive = true; - if (quit_requested) - go_interactive = false; - else if (m_option_data.m_batch && !stopped_for_crash) - go_interactive = false; - + // Now set the input file handle to STDIN and run the command interpreter + // again in interactive mode or repl mode and let the debugger take ownership + // of stdin. if (go_interactive) { m_debugger.SetInputFileHandle(stdin, true);