gdb, gdbserver: detach fork child when detaching from fork parent
authorSimon Marchi <simon.marchi@efficios.com>
Thu, 14 Oct 2021 19:19:49 +0000 (15:19 -0400)
committerSimon Marchi <simon.marchi@efficios.com>
Thu, 28 Oct 2021 20:32:06 +0000 (16:32 -0400)
commit83fa209e249873d7751cdf97f67adbc3062b19e9
tree9d32cd68f6e368de42f146345e1696ad7a495312
parent3b2fb5bda8d95d2e1ea7e0219068edab890ee8f4
gdb, gdbserver: detach fork child when detaching from fork parent

FIXME: we should make target_ops::detach take a pid, not an inferior,
and have the core detach fork childs of pending events (stored in
thread_info's pending waitstatus).

While working with pending fork events, I wondered what would happen if
the user detached an inferior while a thread of that inferior had a
pending fork event.  What happens with the fork child, which is
ptrace-attached by the GDB process (or by GDBserver if using that), but
with the core of GDB not knowing about it.  Sure enough, neither the
core of GDB or the target detach the child process, so GDB (or
GDBserver) just stays ptrace-attached to the process.  The result is
that the fork child process is stuck, while you would expect it to be
detached and run.

I don't think there is anything the core of GDB can do
here, it's up to each target to detach a fork child if detaching a
thread with a pending fork event.  This affects the Linux native target
and the remote target (and probably the other targets that support fork,
but I haven't tried them).

Update the gdb.threads/pending-fork-event.exp to try to detach the
process while a thread has a pending fork event.  In order to verify
that the fork child process is correctly detached and resumes execution
outside of GDB's control, make that process create a file in the test
output directory, and make the test wait $timeout seconds for that file
to appear (it happens instantly if everything goes well).

The test catches a bug in linux-nat.c, also reported as PR 28512
("waitstatus.h:300: internal-error: gdb_signal target_waitstatus::sig()
const: Assertion `m_kind == TARGET_WAITKIND_STOPPED || m_kind ==
TARGET_WAITKIND_SIGNALLED' failed.).  When detaching a thread with a
pending event, get_detach_signal unconditionally fetches the signal
stored in the waitstatus (`tp->pending_waitstatus ().sig ()`).  However,
that is only valid if the pending event is of type
TARGET_WAITKIND_STOPPED, and this is now enforced using assertions (iit
would also be valid for TARGET_WAITKIND_SIGNALLED, but that would mean
the thread does not exist anymore, so we wouldn't be detaching it).  Add
a condition in get_detach_signal to access the signal number only if the
wait status is of kind TARGET_WAITKIND_STOPPED, and use GDB_SIGNAL_0
instead (since the thread was not stopped with a signal to begin with).

Change-Id: I6d811a56f520e3cb92d5ea563ad38976f92e93dd
gdb/linux-nat.c
gdb/remote.c
gdb/testsuite/gdb.threads/pending-fork-event-touch-file.c [new file with mode: 0644]
gdb/testsuite/gdb.threads/pending-fork-event.c
gdb/testsuite/gdb.threads/pending-fork-event.exp
gdbserver/server.cc
This page took 0.025829 seconds and 4 git commands to generate.