Revert "Fix race condition during process detach"

This fix is not correct on its own until D12968 is resolved. Will resumbit once that is done.

llvm-svn: 248702
This commit is contained in:
Pavel Labath 2015-09-28 09:37:51 +00:00
parent 9a132f36c3
commit c8c77d46ef
3 changed files with 43 additions and 36 deletions

View File

@ -3479,7 +3479,7 @@ protected:
}
Error
StopForDestroyOrDetach(lldb::EventSP &exit_event_sp);
HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp);
bool
StateChangedIsExternallyHijacked();

View File

@ -3916,46 +3916,52 @@ Process::Halt (bool clear_thread_plans)
}
Error
Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp)
Process::HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp)
{
Error error;
if (m_public_state.GetValue() == eStateRunning)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
log->Printf("Process::%s() About to stop.", __FUNCTION__);
SendAsyncInterrupt();
// Consume the interrupt event.
TimeValue timeout (TimeValue::Now());
timeout.OffsetWithSeconds(10);
StateType state = WaitForProcessToStop (&timeout, &exit_event_sp);
// If the process exited while we were waiting for it to stop, put the exited event into
// the shared pointer passed in and return. Our caller doesn't need to do anything else, since
// they don't have a process anymore...
if (state == eStateExited || m_private_state.GetValue() == eStateExited)
log->Printf("Process::%s() About to halt.", __FUNCTION__);
error = Halt();
if (error.Success())
{
if (log)
log->Printf("Process::%s() Process exited while waiting to stop.", __FUNCTION__);
return error;
}
else
exit_event_sp.reset(); // It is ok to consume any non-exit stop events
if (state != eStateStopped)
{
if (log)
log->Printf("Process::%s() failed to stop, state is: %s", __FUNCTION__, StateAsCString(state));
// If we really couldn't stop the process then we should just error out here, but if the
// lower levels just bobbled sending the event and we really are stopped, then continue on.
StateType private_state = m_private_state.GetValue();
if (private_state != eStateStopped)
// Consume the halt event.
TimeValue timeout (TimeValue::Now());
timeout.OffsetWithSeconds(1);
StateType state = WaitForProcessToStop (&timeout, &exit_event_sp);
// If the process exited while we were waiting for it to stop, put the exited event into
// the shared pointer passed in and return. Our caller doesn't need to do anything else, since
// they don't have a process anymore...
if (state == eStateExited || m_private_state.GetValue() == eStateExited)
{
if (log)
log->Printf("Process::HaltForDestroyOrDetach() Process exited while waiting to Halt.");
return error;
}
else
exit_event_sp.reset(); // It is ok to consume any non-exit stop events
if (state != eStateStopped)
{
if (log)
log->Printf("Process::HaltForDestroyOrDetach() Halt failed to stop, state is: %s", StateAsCString(state));
// If we really couldn't stop the process then we should just error out here, but if the
// lower levels just bobbled sending the event and we really are stopped, then continue on.
StateType private_state = m_private_state.GetValue();
if (private_state != eStateStopped)
{
return error;
}
}
}
else
{
if (log)
log->Printf("Process::HaltForDestroyOrDetach() Halt got error: %s", error.AsCString());
}
}
return error;
@ -3974,7 +3980,7 @@ Process::Detach (bool keep_stopped)
{
if (DetachRequiresHalt())
{
error = StopForDestroyOrDetach (exit_event_sp);
error = HaltForDestroyOrDetach (exit_event_sp);
if (!error.Success())
{
m_destroy_in_process = false;
@ -4048,7 +4054,7 @@ Process::Destroy (bool force_kill)
EventSP exit_event_sp;
if (DestroyRequiresHalt())
{
error = StopForDestroyOrDetach(exit_event_sp);
error = HaltForDestroyOrDetach(exit_event_sp);
}
if (m_public_state.GetValue() != eStateRunning)
@ -5225,7 +5231,7 @@ public:
break;
case 'i':
if (StateIsRunningState(m_process->GetState()))
m_process->SendAsyncInterrupt();
m_process->Halt();
break;
}
}
@ -5250,8 +5256,8 @@ public:
// Do only things that are safe to do in an interrupt context (like in
// a SIGINT handler), like write 1 byte to a file descriptor. This will
// interrupt the IOHandlerProcessSTDIO::Run() and we can look at the byte
// that was written to the pipe and then call m_process->SendAsyncInterrupt()
// from a much safer location in code.
// that was written to the pipe and then call m_process->Halt() from a
// much safer location in code.
if (m_active)
{
char ch = 'i'; // Send 'i' for interrupt

View File

@ -15,6 +15,7 @@ class AttachResumeTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
@expectedFailureFreeBSD('llvm.org/pr19310')
@expectedFlakeyLinux('llvm.org/pr19310')
@expectedFailureWindows("llvm.org/pr24778")
@skipIfRemote
@dwarf_test