Fix a race condition in Target::Launch

When no hijack listener is set up, the global event listener will
try to pull events off the queue, racing with the event thread.
By always forcing a hijack listener, even when one was not given,
we guarantee that the listener always gets all events.

This was causing problems in synchronous mode with the process
stop event sometimes never being picked up and causing the debugger
to hang while processing a .lldbinit file.

Reviewed by: Jim Ingham
Differential Revision: http://reviews.llvm.org/D8562

llvm-svn: 233315
This commit is contained in:
Zachary Turner 2015-03-26 20:41:14 +00:00
parent 3303eff774
commit e6d213a84a
1 changed files with 23 additions and 14 deletions

View File

@ -2596,26 +2596,23 @@ Target::Launch (ProcessLaunchInfo &launch_info, Stream *stream)
{
EventSP event_sp;
ListenerSP hijack_listener_sp (launch_info.GetHijackListener());
if (!hijack_listener_sp)
{
hijack_listener_sp.reset(new Listener("lldb.Target.Launch.hijack"));
launch_info.SetHijackListener(hijack_listener_sp);
m_process_sp->HijackProcessEvents(hijack_listener_sp.get());
}
StateType state = m_process_sp->WaitForProcessToStop (NULL, &event_sp, false, hijack_listener_sp.get(), NULL);
if (state == eStateStopped)
{
if (launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false)
if (!launch_info.GetFlags().Test(eLaunchFlagStopAtEntry))
{
if (!synchronous_execution)
m_process_sp->RestoreProcessEvents ();
error = m_process_sp->PrivateResume();
if (error.Success())
if (synchronous_execution)
{
// there is a race condition where this thread will return up the call stack to the main command
// handler and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has
// a chance to call PushProcessIOHandler()
m_process_sp->SyncIOHandler(2000);
if (synchronous_execution)
error = m_process_sp->PrivateResume();
if (error.Success())
{
state = m_process_sp->WaitForProcessToStop (NULL, NULL, true, hijack_listener_sp.get(), stream);
const bool must_be_alive = false; // eStateExited is ok, so this must be false
@ -2626,6 +2623,18 @@ Target::Launch (ProcessLaunchInfo &launch_info, Stream *stream)
}
}
else
{
m_process_sp->RestoreProcessEvents();
error = m_process_sp->PrivateResume();
if (error.Success())
{
// there is a race condition where this thread will return up the call stack to the main command
// handler and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has
// a chance to call PushProcessIOHandler()
m_process_sp->SyncIOHandler(2000);
}
}
if (!error.Success())
{
Error error2;
error2.SetErrorStringWithFormat("process resume at entry point failed: %s", error.AsCString());
@ -2634,7 +2643,7 @@ Target::Launch (ProcessLaunchInfo &launch_info, Stream *stream)
}
else
{
assert(synchronous_execution && launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == true);
assert(synchronous_execution && launch_info.GetFlags().Test(eLaunchFlagStopAtEntry));
// Target was stopped at entry as was intended. Need to notify the listeners about it.
m_process_sp->RestoreProcessEvents();