summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
authorCaroline Tice <ctice@apple.com>2011-05-02 20:41:46 +0000
committerCaroline Tice <ctice@apple.com>2011-05-02 20:41:46 +0000
commit969ed3d10f2bed3ef9c4d53114594827fefecf68 (patch)
treeb7055dc7c40247fe6accf64529b215cd455b6f30 /lldb/source
parentf897d3b88bf5b09b7aa142e2033146bdeda5316f (diff)
downloadbcm5719-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.cpp12
-rw-r--r--lldb/source/Commands/CommandObjectBreakpointCommand.cpp3
-rw-r--r--lldb/source/Commands/CommandObjectCommands.cpp5
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp3
-rw-r--r--lldb/source/Commands/CommandObjectTarget.cpp3
-rw-r--r--lldb/source/Core/Debugger.cpp14
-rw-r--r--lldb/source/Core/Event.cpp7
-rw-r--r--lldb/source/Core/InputReader.cpp3
-rw-r--r--lldb/source/Core/StreamAsynchronousIO.cpp52
-rw-r--r--lldb/source/Interpreter/CommandInterpreter.cpp11
-rw-r--r--lldb/source/Interpreter/ScriptInterpreterPython.cpp6
-rw-r--r--lldb/source/Target/Process.cpp3
-rw-r--r--lldb/source/Target/Target.cpp12
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();
}
//--------------------------------------------------------------
OpenPOWER on IntegriCloud