This is an archive of the discontinued LLVM Phabricator instance.

Reset continue_after_async only if neither SIGINIT nor SIGSTOP received
ClosedPublic

Authored by ovyalov on Apr 7 2016, 6:54 PM.

Details

Reviewers
clayborg
Summary

Reset continue_after_async only if neither SIGINIT nor SIGSTOP received - otherwise it leads to stopped inferior when setting breakpoint (when m_interrupt_sent == true and signal is SIGSTOP).

Diff Detail

Event Timeline

ovyalov updated this revision to Diff 52992.Apr 7 2016, 6:54 PM
ovyalov retitled this revision from to Reset continue_after_async only if neither SIGINIT nor SIGSTOP received.
ovyalov updated this object.
ovyalov added a reviewer: clayborg.
ovyalov added a subscriber: lldb-commits.
labath added a subscriber: labath.Apr 8 2016, 1:44 AM

Does this fix an existing test or is a new issue? If it's new (it sounds like it is, as I don't see any test failures), could you also add a test for this. It shouldn't be too difficult to write one... Would something like this:

dbg.SetAsync(true)
process.Continue()
lldbutil.expect_state_changes(self,dbg.GetListener(), [eStateRunning])
target.BreakpointCreateBySourceRegex("// some code which will not get executed by the inferior")
do_some_assertions_on_the_breakpoint()
while dbg.GetListener().WaitForEvent(2, event):
  if SBProcess.GetStateFromEvent(event) == eStateStopped and SBProcess.GetRestartedFromEvent(state):
    continue
  if SBProcess.GetStateFromEvent(event) == eStateRunning:
    continue
  self.fail("Setting a breakpoint generated an unexpected event: %s"%SBDebugger.StateAsCString(SBProcess.GetStateFromEvent(event)));

do the trick?

clayborg accepted this revision.Apr 8 2016, 9:17 AM
clayborg edited edge metadata.

Looks good.

This revision is now accepted and ready to land.Apr 8 2016, 9:17 AM
ovyalov updated this revision to Diff 53054.Apr 8 2016, 12:15 PM
ovyalov edited edge metadata.

Added new TestBreakpointSetRestart test to cover the addressed issue.

Does this fix an existing test or is a new issue? If it's new (it sounds like it is, as I don't see any test failures), could you also add a test for this. It shouldn't be too difficult to write one... Would something like this:

dbg.SetAsync(true)
process.Continue()
lldbutil.expect_state_changes(self,dbg.GetListener(), [eStateRunning])
target.BreakpointCreateBySourceRegex("// some code which will not get executed by the inferior")
do_some_assertions_on_the_breakpoint()
while dbg.GetListener().WaitForEvent(2, event):
  if SBProcess.GetStateFromEvent(event) == eStateStopped and SBProcess.GetRestartedFromEvent(state):
    continue
  if SBProcess.GetStateFromEvent(event) == eStateRunning:
    continue
  self.fail("Setting a breakpoint generated an unexpected event: %s"%SBDebugger.StateAsCString(SBProcess.GetStateFromEvent(event)));

do the trick?

Thanks for suggested test, Pavel.

FYI: According to git bisect, this patch seems to have introduced a new test failure on Windows.

FYI: According to git bisect, this patch seems to have introduced a new test failure on Windows.

Thanks for the report - will fix today.

It's weird in that, if you run the test independently, it passes. But if you run it with the multiprocess test runner (ninja check-lldb), then it fails on this line:

self.fail("Setting a breakpoint generated an unexpected event: %s" % lldb.SBDebugger.StateAsCString(lldb.SBProcess.GetStateFromEvent(event)))

The state in this case is stopped.

It's weird in that, if you run the test independently, it passes. But if you run it with the multiprocess test runner (ninja check-lldb), then it fails on this line:

self.fail("Setting a breakpoint generated an unexpected event: %s" % lldb.SBDebugger.StateAsCString(lldb.SBProcess.GetStateFromEvent(event)))

The state in this case is stopped.

I suspect this test has uncovered a problem in the ProcessWindows implementation. The same problem we were solving here for ProcessGdbRemote.

Namely, the question here is what happens if we try to set a breakpoint while the process is running. ProcessGdbRemote (and I expect ProcessWindows as well) needs to stop the inferior to be able to set the breakpoint. However, since this stop wasn't requested by the user, it should not generate any externally visible stops. The process should be silently resumed after you are done with it (I have no idea how is this supposed to be done with the non-gdb-remote processes).

I suspect the test is flaky for you because of different timings when running under heavy system load, but after the issue is fixed the test should pass 100% of time. Unfortunately, I think this task will be up to you. :)

A random thought: will getchar() block the inferior on windows (because of missing stdio forwarding, et al.). If it wont then this could be the cause of the flakyness. If that's the case, then we can replace that call with something that will surely halt progress, like an infinite loop with sleep or something.