public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Simon Marchi <simon.marchi@polymtl.ca>
To: Pedro Alves <pedro@palves.net>,
	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: Mon, 29 Nov 2021 13:27:57 -0500	[thread overview]
Message-ID: <a7af8e68-fea5-1c0e-b385-bcd05701874c@polymtl.ca> (raw)
In-Reply-To: <ac441aae-f812-f4a5-6d26-a505a5fea055@palves.net>

> 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.

Ok, that sounds good (although not trivial!).

>>  }
>> 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);

Done.

> 
>> +      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.

Right.  In my new versions, the loop has:

      /* Only threads that have a pending fork event.  */
      thread_info *child = target_thread_pending_child (thread);
      if (child == nullptr)
	continue;

In your series, you'll make target_thread_pending_child return the kind,
and you can add a check for the kind.

Simon

  reply	other threads:[~2021-11-29 18:28 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
2021-11-29 18:27       ` Simon Marchi [this message]
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=a7af8e68-fea5-1c0e-b385-bcd05701874c@polymtl.ca \
    --to=simon.marchi@polymtl.ca \
    --cc=gdb-patches@sourceware.org \
    --cc=pedro@palves.net \
    --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).