rr-debugger / rr-debugger/rr

How to handle tracee SIGKILL during `Task::did_waitpid`

Open
#3,581 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
10.7k
Forks
662
Avg merge
2d 3h
Merged PRs (30d)
2

Description

Commit 3ef59d96be8a4b620c34663a6f2d043543ec4f00 does not really work because there are cases where t has actually been reaped but we haven't noticed and with that commit we are unable to make forward progress. To tackle this delicate area without causing more regressions, I've been cleaning up use of ptrace_if_alive, now renamed to ptrace_if_stopped, making it more clear that that function fails when the tracee is not in a ptrace-stop. It can only be called when we thought the tracee was in a ptrace-stop (and we did not resume it), so it can only fail when the tracee got kicked out of the ptrace-stop via SIGKILL or equivalent (e.g. zap_pid_ns_processes). Then I've been auditing callers of ptrace_if_stopped to make sure they do the right thing.

Most cases are fine but there is one particularly hard case: when we get notified of a stop and then in Task::did_waitpid we are unable to read the new register values because the task got SIGKILLed out of that stop. Currently we replace the status with a PTRACE_EVENT_EXIT, which is bad because we're not known to be stopped at all. It doesn't make any sense and it's causing #3504.

Consider the case where the tracee is running along and then gets a signal. We get a ptrace-stop for the signal, then there's a SIGKILL before we can read the registers. We don't know what registers to record with the signal event, and if we don't record the correct registers, we can't replay to the signal. If the tracee eventually reaches a PTRACE_EVENT_EXIT we can get the registers there, but that can be delayed indefinitely by zap_pid_ns_processes or coredumping, so it's hard to route those later register values back to the right point in the trace. It is also possible, at least in older kernels, to not ever see the PTRACE_EVENT_EXIT. Maybe the best thing to do is to ignore the stop completely and consider the tracee as still running, waiting for it to stop again or exit. This does mean the signal stop event will not be recorded --- replay will be as if it never happened --- but I think that is probably reasonable in most or all cases.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at Task::did_waitpid and audit its callers of ptrace_if_stopped, using the discussion of commit 3ef59d96be8a4b620c34663a6f2d043543ec4f00 and issue #3504 as context. Determine how a SIGKILL during a ptrace-stop should be represented without substituting PTRACE_EVENT_EXIT, and verify that the handling does not block forward progress.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, linux
Domain
operating-systems
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.