From: Pedro Alves <pedro@palves.net>
To: Simon Marchi <simon.marchi@polymtl.ca>, gdb-patches@sourceware.org
Cc: Simon Marchi <simon.marchi@efficios.com>
Subject: Re: [PATCH v3 1/7] gdbserver: hide fork child threads from GDB
Date: Fri, 3 Dec 2021 23:30:44 +0000 [thread overview]
Message-ID: <2b69030a-579b-0cef-db0c-77dfefdc52b9@palves.net> (raw)
In-Reply-To: <20211201144500.627736-2-simon.marchi@polymtl.ca>
On 2021-12-01 14:44, Simon Marchi via Gdb-patches wrote:
> From: Simon Marchi <simon.marchi@efficios.com>
>
> This patch aims at fixing a bug where an inferior is unexpectedly
> created when a fork happens at the same time as another event, and that
> other event is reported to GDB first (and the fork event stays pending
> in GDBserver). This happens for example when we step a thread and
> another thread forks at the same time. The bug looks like (if I
> reproduce the included test by hand):
>
> (gdb) show detach-on-fork
> Whether gdb will detach the child of a fork is on.
> (gdb) show follow-fork-mode
> Debugger response to a program call of fork or vfork is "parent".
> (gdb) si
> [New inferior 2]
> Reading /home/simark/build/binutils-gdb/gdb/testsuite/outputs/gdb.threads/step-while-fork-in-other-thread/step-while-fork-in-other-thread from remote target...
> Reading /home/simark/build/binutils-gdb/gdb/testsuite/outputs/gdb.threads/step-while-fork-in-other-thread/step-while-fork-in-other-thread from remote target...
> Reading symbols from target:/home/simark/build/binutils-gdb/gdb/testsuite/outputs/gdb.threads/step-while-fork-in-other-thread/step-while-fork-in-other-thread...
> [New Thread 965190.965190]
> [Switching to Thread 965190.965190]
> Remote 'g' packet reply is too long (expected 560 bytes, got 816 bytes): ... <long series of bytes>
>
> The sequence of events leading to the problem is:
>
> - We are using the all-stop user-visible mode as well as the
> synchronous / all-stop variant of the remote protocol
> - We have two threads, thread A that we single-step and thread B that
> calls fork at the same time
> - GDBserver's linux_process_target::wait pulls the "single step
> complete SIGTRAP" and the "fork" events from the kernel. It
> arbitrarily choses one event to report, it happens to be the
> single-step SIGTRAP. The fork stays pending in the thread_info.
> - GDBserver send that SIGTRAP as a stop reply to GDB
> - While in stop_all_threads, GDB calls update_thread_list, which ends
> up querying the remote thread list using qXfer:threads:read.
> - In the reply, GDBserver includes the fork child created as a result
> of thread B's fork.
> - GDB-side, the remote target sees the new PID, calls
> remote_notice_new_inferior, which ends up unexpectedly creating a new
> inferior, and things go downhill from there.
>
> The problem here is that as long as GDB did not process the fork event,
> it should pretend the fork child does not exist. Ultimately, this event
> will be reported, we'll go through follow_fork, and that process will be
> detached.
>
> The remote target (GDB-side), has some code to remove from the reported
> thread list the threads that are the result of forks not processed by
> GDB yet. But that only works for fork events that have made their way
> to the remote target (GDB-side), but haven't been consumed by the core
> yet, so are still lingering as pending stop replies in the remote target
> (see remove_new_fork_children in remote.c). But in our case, the fork
> event hasn't made its way to the GDB-side remote target. We need to
> implement the same kind of logic GDBserver-side: if there exists a
> thread / inferior that is the result of a fork event GDBserver hasn't
> reported yet, it should exclude that thread / inferior from the reported
> thread list.
>
> This was actually discussed a while ago, but not implemented AFAIK:
>
> https://pi.simark.ca/gdb-patches/1ad9f5a8-d00e-9a26-b0c9-3f4066af5142@redhat.com/#t
> https://sourceware.org/pipermail/gdb-patches/2016-June/133906.html
>
> Implementation details-wise, the fix for this is all in GDBserver. The
> Linux layer of GDBserver already tracks unreported fork parent / child
> relationships using the lwp_info::fork_relative, in order to avoid
> wildcard actions resuming fork childs unknown to GDB. This information
> needs to be made available to the handle_qxfer_threads_worker function,
> so it can filter the reported threads. Add a new thread_pending_parent
> target function that allows the Linux target to return the parent of an
> eventual fork child.
>
> Testing-wise, the test replicates pretty-much the sequence of events
> shown above. The setup of the test makes it such that the main thread
> is about to fork. We stepi the other thread, so that the step completes
> very quickly, in a single event. Meanwhile, the main thread is resumed,
> so very likely has time to call fork. This means that the bug may not
> reproduce every time (if the main thread does not have time to call
> fork), but it will reproduce more often than not. The test fails
> without the fix applied on the native-gdbserver and
> native-extended-gdbserver boards.
>
> At some point I suspected that which thread called fork and which thread
> did the step influenced the order in which the events were reported, and
> therefore the reproducibility of the bug. So I made the test try both
> combinations: main thread forks while other thread steps, and vice
> versa. I'm not sure this is still necessary, but I left it there
> anyway. It doesn't hurt to test a few more combinations.
>
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28288
> Change-Id: I2158d5732fc7d7ca06b0eb01f88cf27bf527b990
OK.
next prev parent reply other threads:[~2021-12-03 23:30 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-01 14:44 [PATCH v3 0/7] Fix handling of pending fork events Simon Marchi
2021-12-01 14:44 ` [PATCH v3 1/7] gdbserver: hide fork child threads from GDB Simon Marchi
2021-12-03 23:30 ` Pedro Alves [this message]
2021-12-01 14:44 ` [PATCH v3 2/7] gdb/linux-nat: factor ptrace-detach code to new detach_one_pid function Simon Marchi
2021-12-03 23:30 ` Pedro Alves
2021-12-01 14:44 ` [PATCH v3 3/7] gdbserver: suppress "Detaching from process" message Simon Marchi
2021-12-03 23:42 ` Pedro Alves
2021-12-04 2:57 ` Simon Marchi
2021-12-01 14:44 ` [PATCH v3 4/7] gdb/remote.c: move some things up Simon Marchi
2021-12-03 23:42 ` Pedro Alves
2021-12-01 14:44 ` [PATCH v3 5/7] gdb/remote.c: refactor pending fork status functions Simon Marchi
2021-12-03 23:43 ` Pedro Alves
2021-12-04 3:03 ` Simon Marchi
2021-12-01 14:44 ` [PATCH v3 6/7] gdb: move clearing of tp->pending_follow to follow_fork_inferior Simon Marchi
2021-12-03 23:43 ` Pedro Alves
2021-12-01 14:45 ` [PATCH v3 7/7] gdb, gdbserver: detach fork child when detaching from fork parent Simon Marchi
2021-12-03 23:44 ` Pedro Alves
2021-12-04 3:36 ` Simon Marchi
2021-12-07 23:25 ` Pedro Alves
2021-12-08 19:54 ` Simon Marchi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2b69030a-579b-0cef-db0c-77dfefdc52b9@palves.net \
--to=pedro@palves.net \
--cc=gdb-patches@sourceware.org \
--cc=simon.marchi@efficios.com \
--cc=simon.marchi@polymtl.ca \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).