Fixed all overlapping prompt issues.
I carefully reviewed exactly how the IOHandlers interact and found places where we weren't properly controlling things. There should be no overlapping prompts and all output should now come out in a controlled fashion.
<rdar://problem/16111293>
llvm-svn: 202525
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 34e0e32..aaacd6e 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -629,8 +629,7 @@
m_instance_name (),
m_loaded_plugins (),
m_event_handler_thread (LLDB_INVALID_HOST_THREAD),
- m_io_handler_thread (LLDB_INVALID_HOST_THREAD),
- m_event_handler_thread_alive(false)
+ m_io_handler_thread (LLDB_INVALID_HOST_THREAD)
{
char instance_cstr[256];
snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID());
@@ -960,13 +959,17 @@
// Got the current top input reader...
IOHandlerSP top_reader_sp (m_input_reader_stack.Top());
- // Push our new input reader
- m_input_reader_stack.Push (reader_sp);
+ // Don't push the same IO handler twice...
+ if (reader_sp.get() != top_reader_sp.get())
+ {
+ // Push our new input reader
+ m_input_reader_stack.Push (reader_sp);
- // Interrupt the top input reader to it will exit its Run() function
- // and let this new input reader take over
- if (top_reader_sp)
- top_reader_sp->Deactivate();
+ // Interrupt the top input reader to it will exit its Run() function
+ // and let this new input reader take over
+ if (top_reader_sp)
+ top_reader_sp->Deactivate();
+ }
}
bool
@@ -985,6 +988,7 @@
if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get())
{
reader_sp->Deactivate();
+ reader_sp->Cancel();
m_input_reader_stack.Pop ();
reader_sp = m_input_reader_stack.Top();
@@ -2769,36 +2773,30 @@
const uint32_t event_type = event_sp->GetType();
ProcessSP process_sp = Process::ProcessEventData::GetProcessFromEvent(event_sp.get());
+ StreamString output_stream;
+ StreamString error_stream;
const bool gui_enabled = IsForwardingEvents();
- bool top_io_handler_hid = false;
- if (gui_enabled == false)
- top_io_handler_hid = HideTopIOHandler();
- assert (process_sp);
+ if (!gui_enabled)
+ {
+ bool pop_process_io_handler = false;
+ assert (process_sp);
- if (event_type & Process::eBroadcastBitSTDOUT)
- {
- // The process has stdout available, get it and write it out to the
- // appropriate place.
- if (top_io_handler_hid)
- GetProcessSTDOUT (process_sp.get(), NULL);
- }
- else if (event_type & Process::eBroadcastBitSTDERR)
- {
- // The process has stderr available, get it and write it out to the
- // appropriate place.
- if (top_io_handler_hid)
- GetProcessSTDERR (process_sp.get(), NULL);
- }
- else if (event_type & Process::eBroadcastBitStateChanged)
- {
- // Drain all stout and stderr so we don't see any output come after
- // we print our prompts
- if (top_io_handler_hid)
+ if (event_type & Process::eBroadcastBitSTDOUT || event_type & Process::eBroadcastBitStateChanged)
{
- StreamFileSP stream_sp (GetOutputFile());
- GetProcessSTDOUT (process_sp.get(), stream_sp.get());
- GetProcessSTDERR (process_sp.get(), NULL);
+ GetProcessSTDOUT (process_sp.get(), &output_stream);
+ }
+
+ if (event_type & Process::eBroadcastBitSTDERR || event_type & Process::eBroadcastBitStateChanged)
+ {
+ GetProcessSTDERR (process_sp.get(), &error_stream);
+ }
+
+ if (event_type & Process::eBroadcastBitStateChanged)
+ {
+
+ // Drain all stout and stderr so we don't see any output come after
+ // we print our prompts
// Something changed in the process; get the event and report the process's current status and location to
// the user.
StateType event_state = Process::ProcessEventData::GetStateFromEvent (event_sp.get());
@@ -2815,9 +2813,12 @@
case eStateStepping:
case eStateDetached:
{
- stream_sp->Printf("Process %" PRIu64 " %s\n",
- process_sp->GetID(),
- StateAsCString (event_state));
+ output_stream.Printf("Process %" PRIu64 " %s\n",
+ process_sp->GetID(),
+ StateAsCString (event_state));
+
+ if (event_state == eStateDetached)
+ pop_process_io_handler = true;
}
break;
@@ -2826,7 +2827,8 @@
break;
case eStateExited:
- process_sp->GetStatus(*stream_sp);
+ process_sp->GetStatus(output_stream);
+ pop_process_io_handler = true;
break;
case eStateStopped:
@@ -2842,20 +2844,20 @@
if (num_reasons == 1)
{
const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), 0);
- stream_sp->Printf("Process %" PRIu64 " stopped and restarted: %s\n",
- process_sp->GetID(),
- reason ? reason : "<UNKNOWN REASON>");
+ output_stream.Printf("Process %" PRIu64 " stopped and restarted: %s\n",
+ process_sp->GetID(),
+ reason ? reason : "<UNKNOWN REASON>");
}
else
{
- stream_sp->Printf("Process %" PRIu64 " stopped and restarted, reasons:\n",
- process_sp->GetID());
+ output_stream.Printf("Process %" PRIu64 " stopped and restarted, reasons:\n",
+ process_sp->GetID());
for (size_t i = 0; i < num_reasons; i++)
{
const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), i);
- stream_sp->Printf("\t%s\n", reason ? reason : "<UNKNOWN REASON>");
+ output_stream.Printf("\t%s\n", reason ? reason : "<UNKNOWN REASON>");
}
}
}
@@ -2929,8 +2931,8 @@
const uint32_t start_frame = 0;
const uint32_t num_frames = 1;
const uint32_t num_frames_with_source = 1;
- process_sp->GetStatus(*stream_sp);
- process_sp->GetThreadStatus (*stream_sp,
+ process_sp->GetStatus(output_stream);
+ process_sp->GetThreadStatus (output_stream,
only_threads_with_stop_reason,
start_frame,
num_frames,
@@ -2940,20 +2942,46 @@
{
uint32_t target_idx = GetTargetList().GetIndexOfTarget(process_sp->GetTarget().shared_from_this());
if (target_idx != UINT32_MAX)
- stream_sp->Printf ("Target %d: (", target_idx);
+ output_stream.Printf ("Target %d: (", target_idx);
else
- stream_sp->Printf ("Target <unknown index>: (");
- process_sp->GetTarget().Dump (stream_sp.get(), eDescriptionLevelBrief);
- stream_sp->Printf (") stopped.\n");
+ output_stream.Printf ("Target <unknown index>: (");
+ process_sp->GetTarget().Dump (&output_stream, eDescriptionLevelBrief);
+ output_stream.Printf (") stopped.\n");
}
+
+ // Pop the process IO handler
+ pop_process_io_handler = true;
}
break;
}
}
- }
- if (top_io_handler_hid)
- RefreshTopIOHandler();
+ if (output_stream.GetSize() || error_stream.GetSize())
+ {
+ StreamFileSP error_stream_sp (GetOutputFile());
+ bool top_io_handler_hid = HideTopIOHandler();
+
+ if (output_stream.GetSize())
+ {
+ StreamFileSP output_stream_sp (GetOutputFile());
+ if (output_stream_sp)
+ output_stream_sp->Write (output_stream.GetData(), output_stream.GetSize());
+ }
+
+ if (error_stream.GetSize())
+ {
+ StreamFileSP error_stream_sp (GetErrorFile());
+ if (error_stream_sp)
+ error_stream_sp->Write (error_stream.GetData(), error_stream.GetSize());
+ }
+
+ if (top_io_handler_hid)
+ RefreshTopIOHandler();
+ }
+
+ if (pop_process_io_handler)
+ process_sp->PopProcessIOHandler();
+ }
}
void