This is an archive of the discontinued LLVM Phabricator instance.

Fix race condition during process detach
ClosedPublic

Authored by labath on Sep 22 2015, 6:48 AM.

Details

Summary

The following situation occured in TestAttachResume:

The inferior was stoped at a breakpoint and we did a continue, immediately followed by a detach.
Since there was a trap instruction under the IP, the continue did a step-over-breakpoint before
resuming the inferior for real. In some cases, the detach command was executed between these two
events (after the step-over stop, but before continue). Here, public state was running, but
private state was stopped. This caused a problem because HaltForDestroyOrDetach was checking the
public state to see whether it needs to stop the process (call Halt()), but Halt() was checking
the private state and concluded that there is nothing for it to do.

Solution: Instead of Halt() call SendAsyncInterrupt(), which will then cause Halt() to be
executed in the context of the private state thread. I also rename HaltForDestroyOrDetach to
reflect it does not call halt directly.

Diff Detail

Repository
rL LLVM

Event Timeline

labath updated this revision to Diff 35371.Sep 22 2015, 6:48 AM
labath updated this revision to Diff 35372.
labath retitled this revision from to Fix race condition during process detach.
labath updated this object.
labath added reviewers: jingham, clayborg.
labath added a subscriber: lldb-commits.

remove some binaries that managed to sneak in

clayborg accepted this revision.Sep 22 2015, 9:28 AM
clayborg edited edge metadata.
This revision is now accepted and ready to land.Sep 22 2015, 9:28 AM

See http://reviews.llvm.org/D12968 also - fix for missed hijacked listener set in Process::HaltForDestroyOrDetach()

This revision was automatically updated to reflect the committed changes.

It looks like this CL is introducing additional latency when destroying process - I noticed 10 seconds delay when destroying Android process and got logs for code with this CL and without:

1443231085.125153000 Process::StopForDestroyOrDetach() About to stop.
1443231085.125225000 Process::WaitForProcessToStop (timeout = 0x7fa9fb5fab28)
1443231085.125243000 Process::WaitForStateChangedEvents (timeout = 0x7fa9fb5fab28, event_sp)...
1443231085.125284000 Process::RunPrivateStateThread (arg = 0x7fa9ec38d470, pid = 20579) woke up with an interrupt - Halting.
1443231085.137527000 Process::SetPrivateState (stopped)
1443231085.137569000 Process::SetPrivateState (stopped) stop_id = 13
1443231085.137646000 Process::WaitForEventsPrivate (timeout = (nil), event_sp)...
1443231085.139090000 Process::ShouldBroadcastEvent (0x7fa9e4003a10) stopped due to an interrupt, state: stopped
1443231085.139159000 Process::ShouldBroadcastEvent (0x7fa9e4003a10) => new state: stopped, last broadcast state: stopped - YES
1443231085.139166000 Process::HandlePrivateEvent (pid = 20579) broadcasting new state stopped (old state running) to public
1443231085.139184000 Process::WaitForEventsPrivate (timeout = (nil), event_sp)...
1443231085.139267000 Process::SetPublicState (state = stopped, restarted = 0)
1443231085.139336000 Process::SetPublicState (stopped) -- unlocking run lock
1443231095.125328000 Process::WaitForStateChangedEvents (timeout = 0x7fa9fb5fab28, event_sp) => invalid
1443231095.125507000 Process::StopForDestroyOrDetach() failed to stop, state is: invalid

1443231549.351362000 Process::HaltForDestroyOrDetach() About to halt.
1443231549.364460000 Process::SetPrivateState (stopped)
1443231549.364475000 Process::SetPrivateState (stopped) stop_id = 13
1443231549.364499000 Process::WaitForProcessToStop (timeout = 0x7f4f34ff6b18)
1443231549.364508000 Process::WaitForStateChangedEvents (timeout = 0x7f4f34ff6b18, event_sp)...
1443231549.364973000 Process::ShouldBroadcastEvent (0x7f4f1c002150) stopped due to an interrupt, state: stopped
1443231549.365040000 Process::ShouldBroadcastEvent (0x7f4f1c002150) => new state: stopped, last broadcast state: stopped - YES
1443231549.365046000 Process::HandlePrivateEvent (pid = 20768) broadcasting new state stopped (old state running) to public
1443231549.365062000 Process::WaitForEventsPrivate (timeout = (nil), event_sp)...
1443231549.365095000 Process::SetPublicState (state = stopped, restarted = 0)
1443231549.365117000 Process::SetPublicState (stopped) -- unlocking run lock
1443231550.364602000 Process::WaitForStateChangedEvents (timeout = 0x7f4f34ff6b18, event_sp) => invalid
1443231550.364682000 Process::HaltForDestroyOrDetach() Halt failed to stop, state is: invalid

So, I believe there is still a problem with stopped state delivery within WaitForProcessToStop which should be fixed in long-term. As quick workaround we can either revert this CL or reduce timeout to avoid 10 second delay upon process termination.

I have reverted this for now. This fix is not complete without D12968.