From: Pedro Alves <palves@redhat.com>
To: "Breazeal, Don" <donb@codesourcery.com>, gdb-patches@sourceware.org
Subject: Re: [PATCH 01/16 v2] Refactor native follow-fork
Date: Fri, 26 Sep 2014 18:13:00 -0000 [thread overview]
Message-ID: <5425ACBF.7080800@redhat.com> (raw)
In-Reply-To: <54132443.5060602@codesourcery.com>
On 09/12/2014 05:50 PM, Breazeal, Don wrote:
> On 9/9/2014 4:09 AM, Pedro Alves wrote:
>> On 09/09/2014 12:54 AM, Breazeal, Don wrote:
>> I'd rather not. That'll just add more technical debt. :-) E.g.,
>> if we can't model this on the few native targets we have, then that'd
>> indicate that remote debugging against one of those targets (when
>> we get to gdb/gdbserver parity), wouldn't be correctly modelled, as
>> you'd be installing those methods in remote.c too. Plus, if we have
>> target_follow_fork_inferior as an extra method in addition
>> to target_follow_fork_inferior, and both are always called in
>> succession, then we might as well _not_ introduce a new target hook,
>> and just call infrun_follow_fork_inferior from the
>> top of linux-nat.c:linux_child_follow_fork, and the top of whatever
>> other target's to_follow_fork method that wants to use it.
>
> I've made modifications to inf_ttrace_follow_fork, inf_ttrace_wait,
> and inf_ptrace_follow_fork in the included patch that I think should
> allow them to work with follow_fork_inferior. Some other adjustments
> were necessary in inf-ttrace.c. Some of the changes weren't strictly
> necessary to get things working with follow_fork_inferior, but it
> seemed appropriate to make all the implementations more consistent.
Thanks.
>>> The changes to inf_ptrace_follow_fork to get it to work with
>>> follow_fork_inferior are straightforward. Making those changes to
>>> inf_ttrace_follow_fork is problematic, primarily because it handles the
>>> moral equivalent of the vfork-done event differently.
>>
>> Can you summarize the differences ?
>
> HP-UX apparently delivers a TTEVT_VFORK event for the parent inferior
> where Linux would report PTRACE_EVENT_VFORK_DONE -- when the child
> process has either execd or exited. inf_ttrace_follow_fork was handling
> the parent VFORK event in-line, where the Linux implementation expects
> a TARGET_WAITKIND_VFORK_DONE event to be reported so it can be handled
> in the generic event code.
>
Right. Linux also used to handle that in-line, before 6c95b8df.
> I've included annotated versions of the original implementations of
> inf_ttrace_follow_fork and inf-ptrace_follow_fork below for reference,
> to explain how I made decisions on the changes. Each annotation is
> a comment beginning with "BLOCK n". If you want to skip past all of
> that you can just search for "Don". :-)
Excellent. That sure made it easier.
>>
>
> My assumptions about how HP-UX ttrace events work:
> - FORK:
> - TTEVT_FORK is reported for both the parent and child processes.
> The event can be reported for the parent or child in any order.
>
> - VFORK:
> - TTEVT_VFORK is reported for both the parent and child
> processes.
> - TTEVT_VFORK is reported for the child first. It is reported
> for the parent when the vfork is "done" as with the Linux
> PTRACE_EVENT_VFORK_DONE event, meaning that the parent has
> called exec or exited. See this comment in inf_ttrace_follow_fork:
>
> /* Wait till we get the TTEVT_VFORK event in the parent.
> This indicates that the child has called exec(3) or has
> exited and that the parent is ready to be traced again. */
>
> The online HP-UX ttrace documentation doesn't really make this
> ordering explicit, but it doesn't contradict the implementation.
Yeah, I can't imagine any way a TTEVT_VFORK could ever be reported to
the parent first. When the parent vforks, it blocks until the child
execs or exits. And the child won't do that until GDB resumes
the child after handling the TTEVT_VFORK that is reported for the
child. So the kernel must always report the child's TTEVT_VFORK first.
> if (follow_child)
> {
> struct thread_info *ti;
> @@ -533,17 +423,22 @@ inf_ttrace_follow_fork (struct target_ops *ops,
> int follow_child,
> inf_ttrace_num_lwps = 1;
> inf_ttrace_num_lwps_in_syscall = 0;
>
> - /* Delete parent. */
> - delete_thread_silent (ptid_build (pid, lwpid, 0));
> - detach_inferior (pid);
> -
> - /* Add child thread. inferior_ptid was already set above. */
> - ti = add_thread_silent (inferior_ptid);
> + ti = find_thread_ptid (inferior_ptid);
> + gdb_assert (ti != NULL);
Replace these with:
ti = inferior_thread ();
> ti->private =
> xmalloc (sizeof (struct inf_ttrace_private_thread_info));
> memset (ti->private, 0,
> sizeof (struct inf_ttrace_private_thread_info));
> }
> + else
> + {
> + pid_t child_pid;
> +
> + /* Following parent. Detach child now. */
> + child_pid = ptid_get_pid (tp->pending_follow.value.related_pid);
> + if (ttrace (TT_PROC_DETACH, child_pid, 0, 0, 0, 0) == -1)
> + perror_with_name (("ttrace"));
> + }
>
> return 0;
> }
> @@ -661,7 +556,6 @@ inf_ttrace_create_inferior (struct target_ops *ops,
> char *exec_file,
> gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
> gdb_assert (inf_ttrace_page_dict.count == 0);
> gdb_assert (inf_ttrace_reenable_page_protections == 0);
> - gdb_assert (inf_ttrace_vfork_ppid == -1);
>
> pid = fork_inferior (exec_file, allargs, env, inf_ttrace_me, NULL,
> inf_ttrace_prepare, NULL, NULL);
> @@ -772,7 +666,6 @@ inf_ttrace_attach (struct target_ops *ops, const
> char *args, int from_tty)
>
> gdb_assert (inf_ttrace_num_lwps == 0);
> gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
> - gdb_assert (inf_ttrace_vfork_ppid == -1);
>
> if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0)
> == -1)
> perror_with_name (("ttrace"));
> @@ -822,11 +715,12 @@ inf_ttrace_detach (struct target_ops *ops, const
> char *args, int from_tty)
> if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1)
> perror_with_name (("ttrace"));
>
> - if (inf_ttrace_vfork_ppid != -1)
> + if (current_inferior ()->vfork_parent != NULL)
> {
> - if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
> + pid_t ppid = current_inferior ()->vfork_parent->pid;
> + if (ttrace (TT_PROC_DETACH, ppid, 0, 0, 0, 0) == -1)
> perror_with_name (("ttrace"));
> - inf_ttrace_vfork_ppid = -1;
> + detach_inferior (ppid);
> }
I think we should just delete this block instead.
We shouldn't be blindly detaching from the parent here.
The user may well still want to debug it. The case of the
user doing "detach" on the child when the parent is waiting
for the the vfork-done should be handled by common code.
(and we should be going through the whole target_detach).
>
> inf_ttrace_num_lwps = 0;
> @@ -850,11 +744,12 @@ inf_ttrace_kill (struct target_ops *ops)
> perror_with_name (("ttrace"));
> /* ??? Is it necessary to call ttrace_wait() here? */
>
> - if (inf_ttrace_vfork_ppid != -1)
> + if (current_inferior ()->vfork_parent != NULL)
> {
> - if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
> + pid_t ppid = current_inferior ()->vfork_parent->pid;
> + if (ttrace (TT_PROC_DETACH, ppid, 0, 0, 0, 0) == -1)
> perror_with_name (("ttrace"));
> - inf_ttrace_vfork_ppid = -1;
> + detach_inferior (ppid);
> }
This too.
>
> target_mourn_inferior ();
> @@ -967,20 +862,6 @@ inf_ttrace_wait (struct target_ops *ops,
> if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
> perror_with_name (("ttrace_wait"));
>
> - if (tts.tts_event == TTEVT_VFORK && tts.tts_u.tts_fork.tts_isparent)
> - {
> - if (inf_ttrace_vfork_ppid != -1)
> - {
> - gdb_assert (inf_ttrace_vfork_ppid == tts.tts_pid);
> -
> - if (ttrace (TT_PROC_DETACH, tts.tts_pid, 0, 0, 0, 0) == -1)
> - perror_with_name (("ttrace"));
> - inf_ttrace_vfork_ppid = -1;
> - }
> -
> - tts.tts_event = TTEVT_NONE;
> - }
> -
> clear_sigint_trap ();
> }
> while (tts.tts_event == TTEVT_NONE);
> @@ -1075,17 +956,23 @@ inf_ttrace_wait (struct target_ops *ops,
> break;
>
> case TTEVT_VFORK:
> - gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
> -
> - related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
> - tts.tts_u.tts_fork.tts_flwpid, 0);
> + if (tts.tts_u.tts_fork.tts_isparent)
> + {
> + if (current_inferior ()->waiting_fork_vfork_done)
I don't think we should have this waiting_fork_vfork_done check here.
This should always be a TARGET_WAITKIND_VFORK_DONE?
> + ourstatus->kind = TARGET_WAITKIND_VFORK_DONE;
> + }
> + else
> + {
> + related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
> + tts.tts_u.tts_fork.tts_flwpid, 0);
>
> - ourstatus->kind = TARGET_WAITKIND_VFORKED;
> - ourstatus->value.related_pid = related_ptid;
> + ourstatus->kind = TARGET_WAITKIND_VFORKED;
> + ourstatus->value.related_pid = related_ptid;
>
> - /* HACK: To avoid touching the parent during the vfork, switch
> - away from it. */
> - inferior_ptid = ptid;
> + /* HACK: To avoid touching the parent during the vfork, switch
> + away from it. */
> + inferior_ptid = ptid;
The core is now aware of the vfork parent inferior. Just delete
this hack.
> + }
> break;
>
> case TTEVT_LWP_CREATE:
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index c18267f..af9cbf8 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -60,6 +60,7 @@
> #include "completer.h"
> #include "target-descriptions.h"
> #include "target-dcache.h"
> +#include "terminal.h"
>
> /* Prototypes for local functions */
>
> @@ -79,6 +80,10 @@ static int restore_selected_frame (void *);
>
> static int follow_fork (void);
>
> +static int follow_fork_inferior (int follow_child, int detach_fork);
> +
> +static void follow_inferior_reset_breakpoints (void);
> +
> static void set_schedlock_func (char *args, int from_tty,
> struct cmd_list_element *c);
>
> @@ -486,9 +491,11 @@ follow_fork (void)
> parent = inferior_ptid;
> child = tp->pending_follow.value.related_pid;
>
> - /* Tell the target to do whatever is necessary to follow
> - either parent or child. */
> - if (target_follow_fork (follow_child, detach_fork))
> + /* Set up inferior(s) as specified by the caller, and tell the
> + target to do whatever is necessary to follow either parent
> + or child. */
> + if (follow_fork_inferior (follow_child, detach_fork)
> + || target_follow_fork (follow_child, detach_fork))
I don't think we should ever call follow_fork_inferior without
calling target_follow_fork, right? I think it'd be clearer if
we tail called target_follow_fork inside follow_fork_inferior.
> {
> /* Target refused to follow, or there's some other reason
> we shouldn't resume. */
> @@ -560,7 +567,242 @@ follow_fork (void)
> return should_resume;
> }
>
> -void
> +/* Handle changes to the inferior list based on the type of fork,
> + which process is being followed, and whether the other process
> + should be detached. On entry inferior_ptid must be the ptid of
> + the fork parent. At return inferior_ptid is the ptid of the
> + followed inferior. */
> +
> +int
> +follow_fork_inferior (int follow_child, int detach_fork)
> +{
> + int has_vforked;
> + int parent_pid, child_pid;
> +
> + has_vforked = (inferior_thread ()->pending_follow.kind
> + == TARGET_WAITKIND_VFORKED);
> + parent_pid = ptid_get_lwp (inferior_ptid);
> + if (parent_pid == 0)
> + parent_pid = ptid_get_pid (inferior_ptid);
> + child_pid
> + = ptid_get_pid (inferior_thread ()->pending_follow.value.related_pid);
> +
> + if (has_vforked
> + && !non_stop /* Non-stop always resumes both branches. */
> + && (!target_is_async_p () || sync_execution)
> + && !(follow_child || detach_fork || sched_multi))
> + {
> + /* The parent stays blocked inside the vfork syscall until the
> + child execs or exits. If we don't let the child run, then
> + the parent stays blocked. If we're telling the parent to run
> + in the foreground, the user will not be able to ctrl-c to get
> + back the terminal, effectively hanging the debug session. */
> + fprintf_filtered (gdb_stderr, _("\
> +Can not resume the parent process over vfork in the foreground while\n\
> +holding the child stopped. Try \"set detach-on-fork\" or \
> +\"set schedule-multiple\".\n"));
> + /* FIXME output string > 80 columns. */
> + return 1;
> + }
> +
Moving this to common code isn't strictly correct, as we'd probably
be able to interrupt the vfork parent in this case when remote
debugging, or not sharing the terminal with the inferior. But let's
put this here for now.
> + else
> + {
> + child_inf->aspace = new_address_space ();
> + child_inf->pspace = add_program_space (child_inf->aspace);
> + child_inf->removable = 1;
> + set_current_program_space (child_inf->pspace);
> + clone_program_space (child_inf->pspace, parent_inf->pspace);
> +
> + /* Let the shared library layer (solib-svr4) learn about
It's not always solib-svr4, so make that e.g., "e.g., solib-svr4" now.
> + else
> + {
> + child_inf->aspace = new_address_space ();
> + child_inf->pspace = add_program_space (child_inf->aspace);
> + child_inf->removable = 1;
> + child_inf->symfile_flags = SYMFILE_NO_READ;
> + set_current_program_space (child_inf->pspace);
> + clone_program_space (child_inf->pspace, parent_pspace);
> +
> + /* Let the shared library layer (solib-svr4) learn about
Likewise.
Otherwise this looks good to me.
Thanks,
Pedro Alves
next prev parent reply other threads:[~2014-09-26 18:13 UTC|newest]
Thread overview: 109+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-07 18:00 [PATCH 00/10] Linux extended-remote fork events Don Breazeal
2014-08-07 18:00 ` [PATCH 04/10] Enhance extended ptrace event setup Don Breazeal
2014-08-13 17:50 ` Breazeal, Don
2014-08-07 18:00 ` [PATCH 06/10] Extended-remote follow fork Don Breazeal
2014-08-07 18:00 ` [PATCH 02/10] Refactor follow-fork message printing Don Breazeal
2014-08-07 18:00 ` [PATCH 03/10] Refactor extended ptrace event status Don Breazeal
2014-08-07 18:00 ` [PATCH 01/10] Refactor native follow-fork Don Breazeal
2014-08-07 18:00 ` [PATCH 05/10] GDBserver clone breakpoint list Don Breazeal
2014-08-07 18:00 ` [PATCH 07/10] Extended-remote arch-specific follow fork Don Breazeal
2014-08-07 18:01 ` [PATCH 09/10] Extended-remote fork catchpoints Don Breazeal
2014-08-07 18:01 ` [PATCH 08/10] Extended-remote follow vfork Don Breazeal
2014-08-07 18:01 ` [PATCH 10/10] Extended-remote fork event documentation Don Breazeal
[not found] ` <83tx5om6zs.fsf@gnu.org>
2014-08-08 15:35 ` Breazeal, Don
2014-08-21 0:29 ` [PATCH 01/16 v2] Refactor native follow-fork Don Breazeal
2014-09-05 14:20 ` Pedro Alves
2014-09-05 18:56 ` Breazeal, Don
2014-09-05 20:20 ` Breazeal, Don
2014-09-09 10:57 ` Pedro Alves
2014-09-08 23:54 ` Breazeal, Don
2014-09-09 11:09 ` Pedro Alves
2014-09-12 16:50 ` Breazeal, Don
2014-09-22 15:53 ` Breazeal, Don
2014-09-26 18:13 ` Pedro Alves [this message]
2014-09-29 18:08 ` Breazeal, Don
2014-09-30 10:56 ` Pedro Alves
2014-09-30 18:43 ` Breazeal, Don
2014-08-21 0:29 ` [Patch 00/16 v2] Linux extended-remote fork and exec events Don Breazeal
2014-09-04 20:57 ` Breazeal, Don
2014-10-31 23:29 ` [PATCH 06/16 v3] Extended-remote Linux follow fork Don Breazeal
2014-11-13 13:00 ` Pedro Alves
2014-11-13 18:53 ` Breazeal, Don
2014-11-13 18:59 ` Pedro Alves
2014-11-13 19:06 ` Breazeal, Don
2014-12-06 0:31 ` Breazeal, Don
2015-01-23 12:53 ` Pedro Alves
2015-01-23 17:18 ` Breazeal, Don
[not found] ` <1422222420-25421-1-git-send-email-donb@codesourcery.com>
2015-01-25 21:49 ` [PATCH v4 5/7] Arch-specific remote " Don Breazeal
2015-02-10 16:37 ` Pedro Alves
2015-01-25 21:49 ` [PATCH v4 6/7] Remote follow vfork Don Breazeal
2015-02-10 16:39 ` Pedro Alves
2015-01-25 21:50 ` [PATCH v4 2/7] Clone remote breakpoints Don Breazeal
2015-01-25 21:50 ` [PATCH v4 1/7] Identify remote fork event support Don Breazeal
2015-02-10 16:34 ` Pedro Alves
2015-01-25 21:58 ` [PATCH v4 7/7] Remote fork catch Don Breazeal
2015-01-26 0:07 ` [PATCH v4 3/7 v3] Extended-remote Linux follow fork Don Breazeal
2015-02-10 16:36 ` Pedro Alves
2015-01-26 0:20 ` [PATCH v4 4/7] Target remote " Don Breazeal
2015-01-12 22:39 ` [PATCH 06/16 v3] Extended-remote Linux " Don Breazeal
2015-01-12 22:49 ` Breazeal, Don
2014-10-31 23:29 ` [PATCH 05/16 v3] GDBserver clone breakpoint list Don Breazeal
2014-10-31 23:29 ` [PATCH 08/16 v3] Extended-remote follow vfork Don Breazeal
2014-10-31 23:29 ` [PATCH 00/16 v3] Linux extended-remote fork and exec events Don Breazeal
2014-11-12 15:54 ` Pedro Alves
2014-11-13 13:41 ` Pedro Alves
2014-11-13 13:51 ` Pedro Alves
2014-11-13 14:58 ` Pedro Alves
2014-11-13 19:14 ` Pedro Alves
2014-10-31 23:29 ` [PATCH 04/16 v3] Determine supported extended-remote features Don Breazeal
2014-11-13 12:59 ` Pedro Alves
2014-11-13 18:28 ` Breazeal, Don
2014-11-13 18:33 ` Pedro Alves
2014-11-13 19:08 ` Pedro Alves
2014-11-13 18:37 ` Breazeal, Don
2014-11-13 18:48 ` Pedro Alves
2014-12-06 0:30 ` Breazeal, Don
2015-01-12 22:36 ` Don Breazeal
2015-01-21 21:02 ` Breazeal, Don
2014-10-31 23:29 ` [PATCH 07/16 v3] Extended-remote arch-specific follow fork Don Breazeal
2014-10-31 23:30 ` [PATCH 12/16 v3] Extended-remote follow exec Don Breazeal
2014-10-31 23:30 ` [PATCH 09/16 v3] Extended-remote fork catchpoints Don Breazeal
2014-10-31 23:30 ` [PATCH 13/16 v3] Extended-remote exec catchpoints Don Breazeal
2014-10-31 23:30 ` [PATCH 10/16 v3] Extended-remote fork event documentation Don Breazeal
2014-10-31 23:30 ` [PATCH 11/16 v3] Extended-remote Linux exit events Don Breazeal
2014-11-13 19:18 ` Pedro Alves
2014-10-31 23:31 ` [PATCH 16/16 v3] Non-stop follow exec tests Don Breazeal
2014-10-31 23:31 ` [PATCH 14/16 v3] Suppress spurious warnings with extended-remote follow exec Don Breazeal
2014-10-31 23:31 ` [PATCH 15/16 v3] Extended-remote exec event documentation Don Breazeal
2014-08-21 0:30 ` [PATCH 02/16 v2] Refactor follow-fork message printing Don Breazeal
2014-09-26 19:52 ` Pedro Alves
2014-09-26 20:14 ` Breazeal, Don
2014-10-03 23:51 ` Breazeal, Don
2014-10-15 16:08 ` Pedro Alves
2014-10-22 23:47 ` Breazeal, Don
2014-10-24 12:35 ` Pedro Alves
2014-10-24 18:45 ` Breazeal, Don
2014-08-21 0:30 ` [PATCH 04/16 v2] Determine supported extended-remote features Don Breazeal
2014-10-15 16:17 ` Pedro Alves
2014-10-21 23:23 ` Breazeal, Don
2014-10-22 21:48 ` Pedro Alves
2014-10-31 23:38 ` Breazeal, Don
2014-08-21 0:30 ` [PATCH 03/16 v2] Refactor ptrace extended event status Don Breazeal
2014-09-09 11:31 ` Pedro Alves
2014-09-19 18:14 ` [pushed] " Breazeal, Don
2014-08-21 0:31 ` [PATCH 07/16 v2] Extended-remote arch-specific follow fork Don Breazeal
2014-09-19 21:26 ` Breazeal, Don
2014-08-21 0:31 ` [PATCH 05/16 v2] GDBserver clone breakpoint list Don Breazeal
2014-10-15 17:40 ` Pedro Alves
2014-10-31 23:44 ` Breazeal, Don
2014-08-21 0:31 ` [PATCH 06/16 v2] Extended-remote Linux follow fork Don Breazeal
2014-09-19 20:57 ` Breazeal, Don
2014-08-21 0:32 ` [PATCH 08/16 v2] Extended-remote follow vfork Don Breazeal
2014-08-21 0:33 ` [PATCH 10/16 v2] Extended-remote fork event documentation Don Breazeal
2014-08-21 0:33 ` [PATCH 11/16 v2] Extended-remote Linux exit events Don Breazeal
2014-08-21 0:33 ` [PATCH 09/16 v2] Extended-remote fork catchpoints Don Breazeal
2014-08-21 0:34 ` [PATCH 12/16 v2] Extended-remote follow exec Don Breazeal
2014-08-21 0:34 ` [PATCH 13/16 v2] Extended-remote exec catchpoints Don Breazeal
2014-08-21 0:35 ` [PATCH 14/16 v2] Suppress spurious warnings with extended-remote follow exec Don Breazeal
2014-08-21 0:36 ` [PATCH 15/16 v2] Extended-remote exec event documentation Don Breazeal
2014-08-21 0:36 ` [PATCH 16/16 v2] Non-stop follow exec tests Don Breazeal
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=5425ACBF.7080800@redhat.com \
--to=palves@redhat.com \
--cc=donb@codesourcery.com \
--cc=gdb-patches@sourceware.org \
/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