public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Pedro Alves <pedro@palves.net>
To: Simon Marchi <simon.marchi@efficios.com>, gdb-patches@sourceware.org
Subject: Re: [PATCH 3/3] gdb, gdbserver: detach fork child when detaching from fork parent
Date: Fri, 26 Nov 2021 22:54:12 +0000	[thread overview]
Message-ID: <ac441aae-f812-f4a5-6d26-a505a5fea055@palves.net> (raw)
In-Reply-To: <20211124200444.614978-4-simon.marchi@efficios.com>

On 2021-11-24 20:04, Simon Marchi via Gdb-patches wrote:

> GDB-side, make the linux-nat and remote targets detach of fork children
> known because of pending fork events.  These pending fork events can be
> stored in thread_info::pending_waitstatus, if the core has consumed the
> event but then saved it for later.  They can also be stored, for the
> linux-nat target, in lwp_info::status and lwp_info::waitstatus.  

...

> For the
> remote target, I suppose that a pending fork event could maybe be in the
> stop reply queue, but I could generate a case where would could detach
> while having pending events there, so I didn't handle that case in this
> patch.

Yes, this can certainly happen.  I don't see a way to reliably stop the
program with an event held in the stop reply queue.  GDB constantly drains the
events asynchronously.  So for a testcase, I think you'd need to take
"constantly hammer" approach.  Something like:

 - enable non-stop / target non-stop 
 - make the test program have a few threads constantly fork and exit the child
   I say multiple threads so that the stop reply queue has a good chance of 
   holding an event unprocessed
 - make the test program call alarm() to set a timeout.  See why below.
 - make the testcase constantly attach / continue -a & / detach

Determining whether the fork child was detached correctly would be done by:

 - the parent/child sharing a pipe.  You'd have an array of pipes, one
   entry per thread.
 - the child writing to the pipe before exiting
 - the parent reading from the pipe after forking

If GDB fails to detach the child, then the parent thread hangs in
the pipe read, and eventually, the parent gets a SIGALRM.

To avoid the case of the test failing, then the parent dying with SIGALRM, and
GDB attaching to the wrong process (because the kernel reused the PID for
something else), you'd make the SIGALRM signal handler set a "timed_out"
global flag, and sleep for a while before exiting the process.  Enough time
so that GDB can always reattach before the process disappears due to SIGALRM.

When GDB reattaches, it first always consults that "timed_out" global, to
know whether the detach-from-children succeeded.  If it is set, the test
FAILs.

> There is a known limitation: we don't remove breakpoints from the
> children before detaching it.  So the children, could hit a trap
> instruction after being detached and crash.  I know this is wrong, and
> it should be fixed, but I would like to handle that later.  The current
> patch doesn't fix everything, but it's a step in the right direction.

*nod*

>  }
> diff --git a/gdbserver/server.cc b/gdbserver/server.cc
> index 7963f2faf267..2f3d5341758f 100644
> --- a/gdbserver/server.cc
> +++ b/gdbserver/server.cc
> @@ -1250,6 +1250,35 @@ handle_detach (char *own_buf)
>    /* We'll need this after PROCESS has been destroyed.  */
>    int pid = process->pid;
>  
> +  /* If this process has an unreported fork child, that child is not known to
> +     GDB, so detach it as well.
> +
> +     Here, we specifically don't want to use "safe iteration", as detaching
> +     another process might delete the next thread in the iteration, which is
> +     the one saved by the safe iterator.  We will never delete the currently
> +     iterated on thread, so standard iteration should be safe.  */
> +  for (thread_info *thread : all_threads)
> +    {
> +      /* Only threads that are of the process we are detaching.  */
> +      if (thread->id.pid () != pid)
> +	continue;
> +
> +      /* Only threads that have a pending fork event.  */
> +      if (thread->fork_child == nullptr)
> +	continue;
> +
> +      process_info *fork_child_process
> +	= find_process_pid (thread->fork_child->id.pid ());

This can be written as:

      process_info *fork_child_process
	= get_thread_process (thread->fork_child);

> +      gdb_assert (fork_child_process != nullptr);


Hmm, in my clone events work, I'm making clone events also set
the fork_parent/fork_child link, since clone events and fork/vfork
events are so similar.  In this spot however, we'll need to skip
detaching the child if the child is a clone child, not a fork child.
I wonder how best to check that.  See comments in the review of patch #1.

> +
> +      int fork_child_pid = fork_child_process->pid;
> +
> +      if (detach_inferior (fork_child_process) != 0)
> +	warning (_("Failed to detach fork child %s, child of %s"),
> +		 target_pid_to_str (ptid_t (fork_child_pid)).c_str (),
> +		 target_pid_to_str (thread->id).c_str ());
> +    }
> +
>    if (detach_inferior (process) != 0)
>      write_enn (own_buf);
>    else
> 


  reply	other threads:[~2021-11-26 22:54 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-29 20:33 [PATCH 1/2] gdbserver: hide fork child threads from GDB Simon Marchi
2021-10-29 20:33 ` [PATCH 2/2] gdb, gdbserver: detach fork child when detaching from fork parent Simon Marchi
2021-11-12 20:54 ` [PATCH 1/2] gdbserver: hide fork child threads from GDB (ping) Simon Marchi
2021-11-24 20:04 ` [PATCH 0/3] Fix handling of pending fork events Simon Marchi
2021-11-24 20:04   ` [PATCH 1/3] gdbserver: hide fork child threads from GDB Simon Marchi
2021-11-26 22:51     ` Pedro Alves
2021-11-29 12:46       ` Simon Marchi
2021-11-29 15:37         ` Pedro Alves
2021-11-24 20:04   ` [PATCH 2/3] gdb/linux-nat: factor ptrace-detach code to new detach_one_pid function Simon Marchi
2021-11-26 22:51     ` Pedro Alves
2021-11-24 20:04   ` [PATCH 3/3] gdb, gdbserver: detach fork child when detaching from fork parent Simon Marchi
2021-11-26 22:54     ` Pedro Alves [this message]
2021-11-29 18:27       ` Simon Marchi
2021-11-24 20:56   ` [PATCH 0/3] Fix handling of pending fork events Simon Marchi
2021-11-26 22:50   ` Pedro Alves

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=ac441aae-f812-f4a5-6d26-a505a5fea055@palves.net \
    --to=pedro@palves.net \
    --cc=gdb-patches@sourceware.org \
    --cc=simon.marchi@efficios.com \
    /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).