lemo updated this revision to Diff 115476.
lemo added a comment.
Split the SIGINT handles fixes into a stanalone patch
https://reviews.llvm.org/D37923
Files:
include/lldb/Core/IOHandler.h
include/lldb/Interpreter/CommandInterpreter.h
source/Commands/CommandObjectTarget.cpp
source/Interpreter/CommandInterpreter.cpp
Index: source/Interpreter/CommandInterpreter.cpp
===================================================================
--- source/Interpreter/CommandInterpreter.cpp
+++ source/Interpreter/CommandInterpreter.cpp
@@ -2677,6 +2677,58 @@
return total_bytes;
}
+void CommandInterpreter::StartHandlingCommand() {
+ auto prev_state = m_command_state.exchange(CommandHandlingState::eInProgress);
+ assert(prev_state == CommandHandlingState::eIdle);
+}
+
+void CommandInterpreter::FinishHandlingCommand() {
+ auto prev_state = m_command_state.exchange(CommandHandlingState::eIdle);
+ assert(prev_state != CommandHandlingState::eIdle);
+}
+
+bool CommandInterpreter::InterruptCommand() {
+ auto in_progress = CommandHandlingState::eInProgress;
+ return m_command_state.compare_exchange_strong(
+ in_progress, CommandHandlingState::eInterrupted);
+}
+
+bool CommandInterpreter::WasInterrupted() const {
+ return m_command_state == CommandHandlingState::eInterrupted;
+}
+
+void CommandInterpreter::PrintCommandOutput(Stream &stream, llvm::StringRef str,
+ bool interruptible) {
+ if (str.empty()) {
+ return;
+ }
+
+ if (interruptible) {
+ // Split the output into lines and poll for interrupt requests
+ const char *data = str.data();
+ size_t size = str.size();
+ while (size > 0 && !WasInterrupted()) {
+ size_t chunk_size = 0;
+ for (; chunk_size < size; ++chunk_size) {
+ assert(data[chunk_size] != '\0');
+ if (data[chunk_size] == '\n') {
+ ++chunk_size;
+ break;
+ }
+ }
+ chunk_size = stream.Write(data, chunk_size);
+ assert(size >= chunk_size);
+ data += chunk_size;
+ size -= chunk_size;
+ }
+ if (size > 0) {
+ stream.Printf("\n... Interrupted.\n");
+ }
+ } else {
+ stream.PutCString(str);
+ }
+}
+
void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
std::string &line) {
const bool is_interactive = io_handler.GetIsInteractive();
@@ -2700,6 +2752,8 @@
line.c_str());
}
+ StartHandlingCommand();
+
lldb_private::CommandReturnObject result;
HandleCommand(line.c_str(), eLazyBoolCalculate, result);
@@ -2710,18 +2764,20 @@
if (!result.GetImmediateOutputStream()) {
llvm::StringRef output = result.GetOutputData();
- if (!output.empty())
- io_handler.GetOutputStreamFile()->PutCString(output);
+ PrintCommandOutput(*io_handler.GetOutputStreamFile(), output,
+ is_interactive);
}
// Now emit the command error text from the command we just executed
if (!result.GetImmediateErrorStream()) {
llvm::StringRef error = result.GetErrorData();
- if (!error.empty())
- io_handler.GetErrorStreamFile()->PutCString(error);
+ PrintCommandOutput(*io_handler.GetErrorStreamFile(), error,
+ is_interactive);
}
}
+ FinishHandlingCommand();
+
switch (result.GetStatus()) {
case eReturnStatusInvalid:
case eReturnStatusSuccessFinishNoResult:
@@ -2777,6 +2833,10 @@
ExecutionContext exe_ctx(GetExecutionContext());
Process *process = exe_ctx.GetProcessPtr();
+ if (InterruptCommand()) {
+ return true;
+ }
+
if (process) {
StateType state = process->GetState();
if (StateIsRunningState(state)) {
Index: source/Commands/CommandObjectTarget.cpp
===================================================================
--- source/Commands/CommandObjectTarget.cpp
+++ source/Commands/CommandObjectTarget.cpp
@@ -2053,6 +2053,9 @@
result.GetOutputStream().EOL();
result.GetOutputStream().EOL();
}
+ if (m_interpreter.WasInterrupted()) {
+ break;
+ }
num_dumped++;
DumpModuleSymtab(
m_interpreter, result.GetOutputStream(),
@@ -2081,6 +2084,9 @@
result.GetOutputStream().EOL();
result.GetOutputStream().EOL();
}
+ if (m_interpreter.WasInterrupted()) {
+ break;
+ }
num_dumped++;
DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
module, m_options.m_sort_order);
@@ -2146,6 +2152,9 @@
" modules.\n",
(uint64_t)num_modules);
for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
+ if (m_interpreter.WasInterrupted()) {
+ break;
+ }
num_dumped++;
DumpModuleSections(
m_interpreter, result.GetOutputStream(),
@@ -2167,6 +2176,9 @@
FindModulesByName(target, arg_cstr, module_list, true);
if (num_matches > 0) {
for (size_t i = 0; i < num_matches; ++i) {
+ if (m_interpreter.WasInterrupted()) {
+ break;
+ }
Module *module = module_list.GetModulePointerAtIndex(i);
if (module) {
num_dumped++;
@@ -2239,6 +2251,9 @@
" modules.\n",
(uint64_t)num_modules);
for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
+ if (m_interpreter.WasInterrupted()) {
+ break;
+ }
if (DumpModuleSymbolVendor(
result.GetOutputStream(),
target_modules.GetModulePointerAtIndexUnlocked(image_idx)))
@@ -2260,6 +2275,9 @@
FindModulesByName(target, arg_cstr, module_list, true);
if (num_matches > 0) {
for (size_t i = 0; i < num_matches; ++i) {
+ if (m_interpreter.WasInterrupted()) {
+ break;
+ }
Module *module = module_list.GetModulePointerAtIndex(i);
if (module) {
if (DumpModuleSymbolVendor(result.GetOutputStream(), module))
@@ -2327,6 +2345,9 @@
if (num_modules > 0) {
uint32_t num_dumped = 0;
for (uint32_t i = 0; i < num_modules; ++i) {
+ if (m_interpreter.WasInterrupted()) {
+ break;
+ }
if (DumpCompileUnitLineTable(
m_interpreter, result.GetOutputStream(),
target_modules.GetModulePointerAtIndexUnlocked(i),
Index: include/lldb/Interpreter/CommandInterpreter.h
===================================================================
--- include/lldb/Interpreter/CommandInterpreter.h
+++ include/lldb/Interpreter/CommandInterpreter.h
@@ -242,6 +242,8 @@
bool repeat_on_empty_command = true,
bool no_context_switching = false);
+ bool WasInterrupted() const;
+
//------------------------------------------------------------------
/// Execute a list of commands in sequence.
///
@@ -522,6 +524,23 @@
StringList &commands_help,
CommandObject::CommandMap &command_map);
+ // An interruptible wrapper around the stream output
+ void PrintCommandOutput(Stream &stream, llvm::StringRef str,
+ bool interruptible);
+
+ // A very simple state machine which models the command handling transitions
+ enum class CommandHandlingState {
+ eIdle,
+ eInProgress,
+ eInterrupted,
+ };
+
+ std::atomic<CommandHandlingState> m_command_state {CommandHandlingState::eIdle};
+
+ void StartHandlingCommand();
+ void FinishHandlingCommand();
+ bool InterruptCommand();
+
Debugger &m_debugger; // The debugger session that this interpreter is
// associated with
ExecutionContextRef m_exe_ctx_ref; // The current execution context to use
Index: include/lldb/Core/IOHandler.h
===================================================================
--- include/lldb/Core/IOHandler.h
+++ include/lldb/Core/IOHandler.h
@@ -195,7 +195,7 @@
enum class Completion { None, LLDBCommand, Expression };
IOHandlerDelegate(Completion completion = Completion::None)
- : m_completion(completion), m_io_handler_done(false) {}
+ : m_completion(completion) {}
virtual ~IOHandlerDelegate() = default;
@@ -296,7 +296,6 @@
protected:
Completion m_completion; // Support for common builtin completions
- bool m_io_handler_done;
};
//----------------------------------------------------------------------
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits