diff options
| author | Caroline Tice <ctice@apple.com> | 2011-05-02 20:41:46 +0000 |
|---|---|---|
| committer | Caroline Tice <ctice@apple.com> | 2011-05-02 20:41:46 +0000 |
| commit | 969ed3d10f2bed3ef9c4d53114594827fefecf68 (patch) | |
| tree | b7055dc7c40247fe6accf64529b215cd455b6f30 /lldb/source | |
| parent | f897d3b88bf5b09b7aa142e2033146bdeda5316f (diff) | |
| download | bcm5719-llvm-969ed3d10f2bed3ef9c4d53114594827fefecf68.tar.gz bcm5719-llvm-969ed3d10f2bed3ef9c4d53114594827fefecf68.zip | |
This patch captures and serializes all output being written by the
command line driver, including the lldb prompt being output by
editline, the asynchronous process output & error messages, and
asynchronous messages written by target stop-hooks.
As part of this it introduces a new Stream class,
StreamAsynchronousIO. A StreamAsynchronousIO object is created with a
broadcaster, who will eventually broadcast the stream's data for a
listener to handle, and an event type indicating what type of event
the broadcaster will broadcast. When the Write method is called on a
StreamAsynchronousIO object, the data is appended to an internal
string. When the Flush method is called on a StreamAsynchronousIO
object, it broadcasts it's data string and clears the string.
Anything in lldb-core that needs to generate asynchronous output for
the end-user should use the StreamAsynchronousIO objects.
I have also added a new notification type for InputReaders, to let
them know that a asynchronous output has been written. This is to
allow the input readers to, for example, refresh their prompts and
lines, if desired. I added the case statements to all the input
readers to catch this notification, but I haven't added any code for
handling them yet (except to the IOChannel input reader).
llvm-svn: 130721
Diffstat (limited to 'lldb/source')
| -rw-r--r-- | lldb/source/API/SBDebugger.cpp | 12 | ||||
| -rw-r--r-- | lldb/source/Commands/CommandObjectBreakpointCommand.cpp | 3 | ||||
| -rw-r--r-- | lldb/source/Commands/CommandObjectCommands.cpp | 5 | ||||
| -rw-r--r-- | lldb/source/Commands/CommandObjectExpression.cpp | 3 | ||||
| -rw-r--r-- | lldb/source/Commands/CommandObjectTarget.cpp | 3 | ||||
| -rw-r--r-- | lldb/source/Core/Debugger.cpp | 14 | ||||
| -rw-r--r-- | lldb/source/Core/Event.cpp | 7 | ||||
| -rw-r--r-- | lldb/source/Core/InputReader.cpp | 3 | ||||
| -rw-r--r-- | lldb/source/Core/StreamAsynchronousIO.cpp | 52 | ||||
| -rw-r--r-- | lldb/source/Interpreter/CommandInterpreter.cpp | 11 | ||||
| -rw-r--r-- | lldb/source/Interpreter/ScriptInterpreterPython.cpp | 6 | ||||
| -rw-r--r-- | lldb/source/Target/Process.cpp | 3 | ||||
| -rw-r--r-- | lldb/source/Target/Target.cpp | 12 |
13 files changed, 130 insertions, 4 deletions
diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp index 84b13ab641e..04f15cbba3f 100644 --- a/lldb/source/API/SBDebugger.cpp +++ b/lldb/source/API/SBDebugger.cpp @@ -640,6 +640,18 @@ SBDebugger::PushInputReader (SBInputReader &reader) } void +SBDebugger::NotifyTopInputReader (InputReaderAction notification) +{ + LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + if (log) + log->Printf ("SBDebugger(%p)::NotifyTopInputReader (%d)", m_opaque_sp.get(), notification); + + if (m_opaque_sp) + m_opaque_sp->NotifyTopInputReader (notification); +} + +void SBDebugger::reset (const DebuggerSP &debugger_sp) { m_opaque_sp = debugger_sp; diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp index a188baebdeb..16466481fcf 100644 --- a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp @@ -466,6 +466,9 @@ CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback } break; + case eInputReaderAsynchronousOutputWritten: + break; + case eInputReaderGotToken: if (bytes && bytes_len && baton) { diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index 142f29d79e7..9d31cf7f1f9 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -975,7 +975,10 @@ CommandObjectCommandsAddRegex::InputReaderCallback (void *baton, case eInputReaderDeactivate: break; - + + case eInputReaderAsynchronousOutputWritten: + break; + case eInputReaderGotToken: while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n')) --bytes_len; diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index ed7824bd823..fa578f49987 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -205,6 +205,9 @@ CommandObjectExpression::MultiLineExpressionCallback case eInputReaderDeactivate: break; + case eInputReaderAsynchronousOutputWritten: + break; + case eInputReaderGotToken: ++cmd_object_expr->m_expr_line_count; if (bytes && bytes_len) diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 958aa2cf047..f7f873cd8f3 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -1032,6 +1032,9 @@ public: } break; + case eInputReaderAsynchronousOutputWritten: + break; + case eInputReaderGotToken: if (bytes && bytes_len && baton) { diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index f1a64b98209..f328c626fd1 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -423,6 +423,20 @@ Debugger::CleanUpInputReaders () } void +Debugger::NotifyTopInputReader (InputReaderAction notification) +{ + InputReaderSP reader_sp (GetCurrentInputReader()); + if (reader_sp) + { + reader_sp->Notify (notification); + + // Flush out any input readers that are done. + while (CheckIfTopInputReaderIsDone ()) + /* Do nothing. */; + } +} + +void Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len) { if (bytes && bytes_len) diff --git a/lldb/source/Core/Event.cpp b/lldb/source/Core/Event.cpp index 8b0ac16e2b6..ac122858c71 100644 --- a/lldb/source/Core/Event.cpp +++ b/lldb/source/Core/Event.cpp @@ -198,3 +198,10 @@ EventDataBytes::GetEventDataFromEvent (const Event *event_ptr) return NULL; } +void +EventDataBytes::SwapBytes (std::string &new_bytes) +{ + m_bytes.swap (new_bytes); +} + + diff --git a/lldb/source/Core/InputReader.cpp b/lldb/source/Core/InputReader.cpp index fc94bed0834..26f7f842314 100644 --- a/lldb/source/Core/InputReader.cpp +++ b/lldb/source/Core/InputReader.cpp @@ -327,6 +327,9 @@ InputReader::Notify (InputReaderAction notification) m_active = false; break; + case eInputReaderAsynchronousOutputWritten: + break; + case eInputReaderInterrupt: case eInputReaderEndOfFile: break; diff --git a/lldb/source/Core/StreamAsynchronousIO.cpp b/lldb/source/Core/StreamAsynchronousIO.cpp new file mode 100644 index 00000000000..84659c6e16b --- /dev/null +++ b/lldb/source/Core/StreamAsynchronousIO.cpp @@ -0,0 +1,52 @@ +//===-- StreamBroadcast.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> + +#include "lldb/lldb-private.h" +#include "lldb/Core/Broadcaster.h" +#include "lldb/Core/Event.h" +#include "lldb/Core/StreamAsynchronousIO.h" + +using namespace lldb; +using namespace lldb_private; + + +StreamAsynchronousIO::StreamAsynchronousIO (Broadcaster &broadcaster, uint32_t broadcast_event_type) : + Stream (0, 4, eByteOrderBig), + m_broadcaster (broadcaster), + m_broadcast_event_type (broadcast_event_type), + m_accumulated_data () +{ +} + +StreamAsynchronousIO::~StreamAsynchronousIO () +{ +} + +void +StreamAsynchronousIO::Flush () +{ + if (m_accumulated_data.GetSize() > 0) + { + std::auto_ptr<EventDataBytes> data_bytes_ap (new EventDataBytes); + // Let's swap the bytes to avoid LARGE string copies. + data_bytes_ap->SwapBytes (m_accumulated_data.GetString()); + EventSP new_event_sp (new Event (m_broadcast_event_type, data_bytes_ap.release())); + m_broadcaster.BroadcastEvent (new_event_sp); + m_accumulated_data.Clear(); + } +} + +int +StreamAsynchronousIO::Write (const void *s, size_t length) +{ + m_accumulated_data.Write (s, length); + return length; +} diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index a36d9c299e8..16e5f3b75af 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -1226,7 +1226,10 @@ CommandInterpreter::GetConfirmationInputReaderCallback out_file.Flush (); } break; - + + case eInputReaderAsynchronousOutputWritten: + break; + case eInputReaderGotToken: if (bytes_len == 0) { @@ -1642,6 +1645,12 @@ CommandInterpreter::HandleCommands (const StringList &commands, } } + if (result.GetImmediateOutputStream()) + result.GetImmediateOutputStream()->Flush(); + + if (result.GetImmediateErrorStream()) + result.GetImmediateErrorStream()->Flush(); + // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution // could be running (for instance in Breakpoint Commands. // So we check the return value to see if it is has running in it. diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 10b9792f009..47302be0ee4 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -639,6 +639,9 @@ ScriptInterpreterPython::InputReaderCallback script_interpreter->EnterSession (); break; + case eInputReaderAsynchronousOutputWritten: + break; + case eInputReaderInterrupt: ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "raise KeyboardInterrupt\n", 24); break; @@ -1047,6 +1050,9 @@ ScriptInterpreterPython::GenerateBreakpointOptionsCommandCallback } break; + case eInputReaderAsynchronousOutputWritten: + break; + case eInputReaderGotToken: { std::string temp_string (bytes, bytes_len); diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 8e96c716e74..7bdccdaf4d0 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -3183,6 +3183,9 @@ Process::ProcessInputReaderCallback (void *baton, case eInputReaderReactivate: break; + case eInputReaderAsynchronousOutputWritten: + break; + case eInputReaderGotToken: { Error error; diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 11804798490..a023bf5b764 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -20,6 +20,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/Event.h" #include "lldb/Core/Log.h" +#include "lldb/Core/StreamAsynchronousIO.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" #include "lldb/Core/ValueObject.h" @@ -1104,8 +1105,12 @@ Target::RunStopHooks () if (num_exe_ctx == 0) return; - result.SetImmediateOutputFile (m_debugger.GetOutputFile().GetStream()); - result.SetImmediateErrorFile (m_debugger.GetErrorFile().GetStream()); + StreamSP output_stream (new StreamAsynchronousIO (m_debugger.GetCommandInterpreter(), + CommandInterpreter::eBroadcastBitAsynchronousOutputData)); + StreamSP error_stream (new StreamAsynchronousIO (m_debugger.GetCommandInterpreter(), + CommandInterpreter::eBroadcastBitAsynchronousErrorData)); + result.SetImmediateOutputStream (output_stream); + result.SetImmediateErrorStream (error_stream); bool keep_going = true; bool hooks_ran = false; @@ -1176,6 +1181,9 @@ Target::RunStopHooks () } if (hooks_ran) result.AppendMessage ("\n** End Stop Hooks **\n"); + + result.GetImmediateOutputStream()->Flush(); + result.GetImmediateErrorStream()->Flush(); } //-------------------------------------------------------------- |

