Skip to content

Fix restart bugs (DON'T MERGE) - #1257

Closed
rocallahan wants to merge 4 commits into
rr-debugger:masterfrom
rocallahan:restarts
Closed

rocallahan wants to merge 4 commits into
rr-debugger:masterfrom
rocallahan:restarts

Conversation

@rocallahan

Copy link
Copy Markdown
Collaborator

This causes call_function to fail because its final "cont" command does not return to the replay session. I haven't figured that out yet, but I wanted to post my work and get some advice.

The test included in this PR currently fails for two main reasons:

  1. calling atomic_printf("hello%s", "kitty") fails. Actually the simpler version atomic_printf("hello") also fails, because gdb rigs a call to malloc() to allocate space for the string, and after that call we end the diversion session; gdb does more set-reg and set-mem calls to set up the atomic_printf, which are ignored, then its vCont resumes the replay session.
  2. gdb "restart" and "run" commands during a diversion session cause an rr assertion failure.
    Patches to make Firefox work again #2 is the real bug I was trying to fix. The fix for that is trivial. But along the way I discovered bug Various changes to get things building and working on my 64-bit Fedora 17 system #1.

@rocallahan

Copy link
Copy Markdown
Collaborator Author

When I call atomic_printf("hello") from gdb, here's what happens:

  • gdb reads siginfo (triggering diversion)
  • gdb stores breakpoint instruction
  • gdb reads siginfo again
  • gdb stores breakpoint instruction again
  • gdb sets up malloc() call frame memory and registers ESP,EBP,EIP
  • gdb does a Cont to perform the malloc, and grabs the register results
  • gdb writes siginfo (trigger diversion to start dying)
  • gdb sets a bunch of registers. Looks like it's restoring them to their old values.
  • gdb sets up the atomic_printf call frame memory and registers (using the block malloced earlier)
  • gdb does a Cont to perform the atomic_printf
  • gdb writes siginfo again
  • gdb writes some more registers (restoring them I guess)

There's some irrelevant breakpoint setting and clearing in there.

It looks like the two siginfo reads correspond to calling atomic_printf() and malloc(), and they occur together because of the way these calls are nested. I guess reviving the diversion session on register writes causes test failures because the writes to restore register state revive the session.

…t restarts) as valid reasons to end a diversion.
Also tests complex tracee function call atomic_printf("hello%s", "kitty"),
which triggered an rr bug where the diversion session died too early, after
the malloc() allocating space for the first string.
@rocallahan

Copy link
Copy Markdown
Collaborator Author

OK, these new commits pass tests. Basically we allow gdb to restore registers to their old values after a siginfo write without reviving the diversion. Any other register writes, or any memory writes, revive the diversion.

@cgjones, does this approach seem OK?

@joneschrisg

Copy link
Copy Markdown
Contributor

@cgjones, does this approach seem OK?

I think I understand this, and it seems OK. I wonder if it's extra complex though: would it have sufficed to "addref" the diversion on each READ_SIGINFO and then unref on WRITE_SIGINFO? (I was originally going to add this, but I changed my mind because I didn't want to rely on gdb pairing READ/WRITE_SIGINFO requests. We can test that though.)

@joneschrisg

Copy link
Copy Markdown
Contributor

Here's an alternate patch that implements the ref/unref approach

joneschrisg@8064161

Passes your test. A bit simpler; what do you think?

@joneschrisg

Copy link
Copy Markdown
Contributor

With a fairly complicated nested call,

(gdb) printf "%d : %d\n", atomic_printf("hello%d\n", atomic_printf("hello%s\n", "kitty")), atomic_printf("hello%d\n", atomic_printf("hello%s\n", "kitty"))

gdb nests its READ/WRITE_SIGINFO requests in the right way for rr to destroy the diversion at the right time. Not sure which assumption is less shaky ...

@rocallahan

Copy link
Copy Markdown
Collaborator Author

I like your approach better!

But we need more descriptive names than ref()/unref(). At least diversion_ref()/diversion_unref().

@joneschrisg

Copy link
Copy Markdown
Contributor

But we need more descriptive names than ref()/unref(). At least diversion_ref()/diversion_unref().

OK, I made that change and added more assertions about these interfaces only being used when is_diversion.

@rocallahan
rocallahan deleted the restarts branch November 24, 2014 10:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants