From: Daniel Jacobowitz Date: Wed, 11 Dec 2002 02:04:45 +0000 (+0000) Subject: * config/pa/nm-hppah.h (CHILD_POST_FOLLOW_VFORK): Change to X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6604731ba7c2a5b3bffcf6ff2831b77ff09a92aa;p=binutils-gdb.git * config/pa/nm-hppah.h (CHILD_POST_FOLLOW_VFORK): Change to CHILD_FOLLOW_FORK. * hppah-nat.c (saved_vfork_pid): Add. (child_post_follow_vfork): Remove. (child_follow_fork): New function. (child_wait): Call detach_breakpoints after receiving the child vfork. Call child_resume directly instead of going through resume (). Make sure we have the exec before reporting the vfork. * inferior.h (follow_inferior_reset_breakpoints): Add prototype. * infrun.c (follow_fork, follow_vfork, follow_inferior_fork): Remove. (follow_fork): New function. Call target_follow_fork. (follow_inferior_reset_breakpoints): New function broken out from old follow_inferior_fork. (resume): Remove hack to follow exec after vfork. * inftarg.c (child_post_follow_vfork): Remove. (child_follow_fork): New function. (init_child_ops): Replace to_post_follow_vfork with to_follow_fork. * target.c (cleanup_target): Replace to_post_follow_vfork with to_follow_fork. (update_current_target): Likewise. (setup_target_debug): Likewise. (debug_to_post_follow_vfork): Remove. (debug_to_follow_fork): New function. * target.h (struct target_ops): Replace to_post_folow_vfork with to_follow_fork. (child_post_follow_vfork): Remove prototype. (child_follow_fork): Add prototype. (target_post_follow_vfork): Remove macro. (target_follow_fork): Add macro. testsuite/ * gdb.base/foll-vfork.exp: Re-enable test on HP/UX. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c427bf0f405..d002d3d9f8b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,35 @@ +2002-12-10 Daniel Jacobowitz + + * config/pa/nm-hppah.h (CHILD_POST_FOLLOW_VFORK): Change to + CHILD_FOLLOW_FORK. + * hppah-nat.c (saved_vfork_pid): Add. + (child_post_follow_vfork): Remove. + (child_follow_fork): New function. + (child_wait): Call detach_breakpoints after receiving the child vfork. + Call child_resume directly instead of going through resume (). + Make sure we have the exec before reporting the vfork. + * inferior.h (follow_inferior_reset_breakpoints): Add prototype. + * infrun.c (follow_fork, follow_vfork, follow_inferior_fork): Remove. + (follow_fork): New function. Call target_follow_fork. + (follow_inferior_reset_breakpoints): New function broken out from + old follow_inferior_fork. + (resume): Remove hack to follow exec after vfork. + * inftarg.c (child_post_follow_vfork): Remove. + (child_follow_fork): New function. + (init_child_ops): Replace to_post_follow_vfork with to_follow_fork. + * target.c (cleanup_target): Replace to_post_follow_vfork with + to_follow_fork. + (update_current_target): Likewise. + (setup_target_debug): Likewise. + (debug_to_post_follow_vfork): Remove. + (debug_to_follow_fork): New function. + * target.h (struct target_ops): Replace to_post_folow_vfork with + to_follow_fork. + (child_post_follow_vfork): Remove prototype. + (child_follow_fork): Add prototype. + (target_post_follow_vfork): Remove macro. + (target_follow_fork): Add macro. + 2002-12-10 Daniel Jacobowitz * hppah-nat.c (saved_child_execd_pathname, saved_vfork_state): New. diff --git a/gdb/config/pa/nm-hppah.h b/gdb/config/pa/nm-hppah.h index 26b4c5bd5cd..54fe806eeec 100644 --- a/gdb/config/pa/nm-hppah.h +++ b/gdb/config/pa/nm-hppah.h @@ -65,7 +65,7 @@ /* In hppah-nat.c: */ #define FETCH_INFERIOR_REGISTERS #define CHILD_XFER_MEMORY -#define CHILD_POST_FOLLOW_VFORK +#define CHILD_FOLLOW_FORK /* While this is for use by threaded programs, it doesn't appear * to hurt non-threaded ones. This is used in infrun.c: */ diff --git a/gdb/hppah-nat.c b/gdb/hppah-nat.c index d7919e6cef8..8ff6c28a7bc 100644 --- a/gdb/hppah-nat.c +++ b/gdb/hppah-nat.c @@ -385,6 +385,7 @@ child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, } char *saved_child_execd_pathname = NULL; +int saved_vfork_pid; enum { STATE_NONE, STATE_GOT_CHILD, @@ -393,48 +394,121 @@ enum { STATE_FAKE_EXEC } saved_vfork_state = STATE_NONE; -void -child_post_follow_vfork (int parent_pid, int followed_parent, int child_pid, - int followed_child) +int +child_follow_fork (int follow_child) { - /* Are we a debugger that followed the parent of a vfork? If so, - then recall that the child's vfork event was delivered to us - first. And, that the parent was suspended by the OS until the - child's exec or exit events were received. - - Upon receiving that child vfork, then, we were forced to remove - all breakpoints in the child and continue it so that it could - reach the exec or exit point. - - But also recall that the parent and child of a vfork share the - same address space. Thus, removing bp's in the child also - removed them from the parent. - - Now that the child has safely exec'd or exited, we must restore - the parent's breakpoints before we continue it. Else, we may - cause it run past expected stopping points. */ - if (followed_parent) + ptid_t last_ptid; + struct target_waitstatus last_status; + int has_vforked; + int parent_pid, child_pid; + + get_last_target_status (&last_ptid, &last_status); + has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED); + parent_pid = ptid_get_pid (last_ptid); + child_pid = last_status.value.related_pid; + + /* At this point, if we are vforking, breakpoints were already + detached from the child in child_wait; and the child has already + called execve(). If we are forking, both the parent and child + have breakpoints inserted. */ + + if (! follow_child) { - reattach_breakpoints (parent_pid); + if (! has_vforked) + { + detach_breakpoints (child_pid); +#ifdef SOLIB_REMOVE_INFERIOR_HOOK + SOLIB_REMOVE_INFERIOR_HOOK (child_pid); +#endif + } + + /* Detach from the child. */ + target_require_detach (child_pid, "", 1); + + /* The parent and child of a vfork share the same address space. + Also, on some targets the order in which vfork and exec events + are received for parent in child requires some delicate handling + of the events. + + For instance, on ptrace-based HPUX we receive the child's vfork + event first, at which time the parent has been suspended by the + OS and is essentially untouchable until the child's exit or second + exec event arrives. At that time, the parent's vfork event is + delivered to us, and that's when we see and decide how to follow + the vfork. But to get to that point, we must continue the child + until it execs or exits. To do that smoothly, all breakpoints + must be removed from the child, in case there are any set between + the vfork() and exec() calls. But removing them from the child + also removes them from the parent, due to the shared-address-space + nature of a vfork'd parent and child. On HPUX, therefore, we must + take care to restore the bp's to the parent before we continue it. + Else, it's likely that we may not stop in the expected place. (The + worst scenario is when the user tries to step over a vfork() call; + the step-resume bp must be restored for the step to properly stop + in the parent after the call completes!) + + Sequence of events, as reported to gdb from HPUX: + + Parent Child Action for gdb to take + ------------------------------------------------------- + 1 VFORK Continue child + 2 EXEC + 3 EXEC or EXIT + 4 VFORK + + Now that the child has safely exec'd or exited, we must restore + the parent's breakpoints before we continue it. Else, we may + cause it run past expected stopping points. */ + + if (has_vforked) + reattach_breakpoints (parent_pid); } + else + { + char child_pid_spelling[40]; + + /* Needed to keep the breakpoint lists in sync. */ + if (! has_vforked) + detach_breakpoints (child_pid); + + /* Before detaching from the parent, remove all breakpoints from it. */ + remove_breakpoints (); - /* If we followed the parent, don't try to follow the child's exec. */ - if (saved_vfork_state != STATE_GOT_PARENT && saved_vfork_state != STATE_FAKE_EXEC) - fprintf_unfiltered (gdb_stdout, "hppa: post follow vfork: confused state\n"); + /* Also reset the solib inferior hook from the parent. */ +#ifdef SOLIB_REMOVE_INFERIOR_HOOK + SOLIB_REMOVE_INFERIOR_HOOK (PIDGET (inferior_ptid)); +#endif + + /* Detach from the parent. */ + target_detach (NULL, 1); + + /* Attach to the child. */ + inferior_ptid = pid_to_ptid (child_pid); + sprintf (child_pid_spelling, "%d", child_pid); - if (followed_parent || saved_vfork_state == STATE_GOT_PARENT) - saved_vfork_state = STATE_NONE; + target_require_attach (child_pid_spelling, 1); + + /* If we vforked, then we've also execed by now. The exec will be + reported momentarily. follow_exec () will handle breakpoints, so + we don't have to.. */ + if (!has_vforked) + follow_inferior_reset_breakpoints (); + } - /* Are we a debugger that followed the child of a vfork? If so, - then recall that we don't actually acquire control of the child - until after it has exec'd or exited. */ - if (followed_child) + if (has_vforked) { - /* If the child has exited, then there's nothing for us to do. - In the case of an exec event, we'll let that be handled by - the normal mechanism that notices and handles exec events, in - resume(). */ + /* If we followed the parent, don't try to follow the child's exec. */ + if (saved_vfork_state != STATE_GOT_PARENT + && saved_vfork_state != STATE_FAKE_EXEC) + fprintf_unfiltered (gdb_stdout, + "hppa: post follow vfork: confused state\n"); + + if (! follow_child || saved_vfork_state == STATE_GOT_PARENT) + saved_vfork_state = STATE_NONE; + else + return 1; } + return 0; } /* Format a process id, given PID. Be sure to terminate @@ -592,15 +666,28 @@ child_wait (ptid_t ptid, struct target_waitstatus *ourstatus) if (saved_vfork_state == STATE_GOT_CHILD) { child_post_startup_inferior (pid_to_ptid (pid)); - ourstatus->kind = TARGET_WAITKIND_SPURIOUS; - return pid_to_ptid (pid); + detach_breakpoints (pid); +#ifdef SOLIB_REMOVE_INFERIOR_HOOK + SOLIB_REMOVE_INFERIOR_HOOK (pid); +#endif + child_resume (pid_to_ptid (pid), 0, TARGET_SIGNAL_0); + ourstatus->kind = TARGET_WAITKIND_IGNORE; + return pid_to_ptid (related_pid); } - else + else if (saved_vfork_state == STATE_FAKE_EXEC) { ourstatus->kind = TARGET_WAITKIND_VFORKED; ourstatus->value.related_pid = related_pid; return pid_to_ptid (pid); } + else + { + /* We saw the parent's vfork, but we haven't seen the exec yet. + Wait for it, for simplicity's sake. It should be pending. */ + saved_vfork_pid = related_pid; + ourstatus->kind = TARGET_WAITKIND_IGNORE; + return pid_to_ptid (pid); + } } if (hpux_has_execd (pid, &execd_pathname)) @@ -608,27 +695,32 @@ child_wait (ptid_t ptid, struct target_waitstatus *ourstatus) /* On HP-UX, events associated with a vforking inferior come in threes: a vfork event for the child (always first), followed a vfork event for the parent and an exec event for the child. - The latter two can come in either order. - - If we get the parent vfork event first, life's good: We follow - either the parent or child, and then the child's exec event is - a "don't care". - - But if we get the child's exec event first, then we delay - responding to it until we handle the parent's vfork. Because, - otherwise we can't satisfy a "catch vfork". */ - if (saved_vfork_state == STATE_GOT_CHILD) + The latter two can come in either order. Make sure we get + both. */ + if (saved_vfork_state != STATE_NONE) { - saved_child_execd_pathname = execd_pathname; - saved_vfork_state = STATE_GOT_EXEC; + if (saved_vfork_state == STATE_GOT_CHILD) + { + saved_vfork_state = STATE_GOT_EXEC; + /* On HP/UX with ptrace, the child must be resumed before + the parent vfork event is delivered. A single-step + suffices. */ + if (RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK ()) + target_resume (pid_to_ptid (pid), 1, TARGET_SIGNAL_0); + ourstatus->kind = TARGET_WAITKIND_IGNORE; + } + else if (saved_vfork_state == STATE_GOT_PARENT) + { + saved_vfork_state = STATE_FAKE_EXEC; + ourstatus->kind = TARGET_WAITKIND_VFORKED; + ourstatus->value.related_pid = saved_vfork_pid; + } + else + fprintf_unfiltered (gdb_stdout, + "hppa: exec: unexpected state\n"); - /* On HP/UX with ptrace, the child must be resumed before - the parent vfork event is delivered. A single-step - suffices. */ - if (RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK ()) - target_resume (pid_to_ptid (pid), 1, TARGET_SIGNAL_0); + saved_child_execd_pathname = execd_pathname; - ourstatus->kind = TARGET_WAITKIND_IGNORE; return inferior_ptid; } diff --git a/gdb/inferior.h b/gdb/inferior.h index 84b45698f3c..a9bbd59496d 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -304,6 +304,8 @@ extern int signal_pass_update (int, int); extern void get_last_target_status(ptid_t *ptid, struct target_waitstatus *status); +extern void follow_inferior_reset_breakpoints (void); + /* From infcmd.c */ extern void tty_command (char *, int); diff --git a/gdb/infrun.c b/gdb/infrun.c index b96e1c7a254..0bb2e753d8c 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -66,12 +66,7 @@ static int restore_selected_frame (void *); static void build_infrun (void); -static void follow_inferior_fork (int parent_pid, int child_pid, - int has_forked, int has_vforked); - -static void follow_fork (int parent_pid, int child_pid); - -static void follow_vfork (int parent_pid, int child_pid); +static int follow_fork (); static void set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c); @@ -384,15 +379,11 @@ static const char *follow_fork_mode_kind_names[] = { static const char *follow_fork_mode_string = follow_fork_mode_parent; -static void -follow_inferior_fork (int parent_pid, int child_pid, int has_forked, - int has_vforked) +static int +follow_fork () { - int followed_parent = 0; - int followed_child = 0; - - /* Which process did the user want us to follow? */ const char *follow_mode = follow_fork_mode_string; + int follow_child = (follow_mode == follow_fork_mode_child); /* Or, did the user not know, and want us to ask? */ if (follow_fork_mode_string == follow_fork_mode_ask) @@ -402,138 +393,36 @@ follow_inferior_fork (int parent_pid, int child_pid, int has_forked, /* follow_mode = follow_fork_mode_...; */ } - /* If we're to be following the parent, then detach from child_pid. - We're already following the parent, so need do nothing explicit - for it. */ - if (follow_mode == follow_fork_mode_parent) - { - followed_parent = 1; - - /* We're already attached to the parent, by default. */ - - /* Before detaching from the child, remove all breakpoints from - it. (This won't actually modify the breakpoint list, but will - physically remove the breakpoints from the child.) */ - detach_breakpoints (child_pid); -#ifdef SOLIB_REMOVE_INFERIOR_HOOK - SOLIB_REMOVE_INFERIOR_HOOK (child_pid); -#endif - - /* Detach from the child. */ - dont_repeat (); - - target_require_detach (child_pid, "", 1); - } - - /* If we're to be following the child, then attach to it, detach - from inferior_ptid, and set inferior_ptid to child_pid. */ - else if (follow_mode == follow_fork_mode_child) - { - char child_pid_spelling[100]; /* Arbitrary length. */ - - followed_child = 1; - - /* Before detaching from the parent, detach all breakpoints from - the child. Note that this only works if we're following vforks - right away; if we've exec'd then the breakpoints are already detached - and the shadow contents are out of date. */ - detach_breakpoints (child_pid); - - /* Before detaching from the parent, remove all breakpoints from it. */ - remove_breakpoints (); - - /* Also reset the solib inferior hook from the parent. */ -#ifdef SOLIB_REMOVE_INFERIOR_HOOK - SOLIB_REMOVE_INFERIOR_HOOK (PIDGET (inferior_ptid)); -#endif - - /* Detach from the parent. */ - dont_repeat (); - target_detach (NULL, 1); - - /* Attach to the child. */ - inferior_ptid = pid_to_ptid (child_pid); - sprintf (child_pid_spelling, "%d", child_pid); - dont_repeat (); - - target_require_attach (child_pid_spelling, 1); - - /* Was there a step_resume breakpoint? (There was if the user - did a "next" at the fork() call.) If so, explicitly reset its - thread number. - - step_resumes are a form of bp that are made to be per-thread. - Since we created the step_resume bp when the parent process - was being debugged, and now are switching to the child process, - from the breakpoint package's viewpoint, that's a switch of - "threads". We must update the bp's notion of which thread - it is for, or it'll be ignored when it triggers... */ - /* As above, if we're following vforks at exec time then resetting the - step resume breakpoint is probably wrong. */ - if (step_resume_breakpoint) - breakpoint_re_set_thread (step_resume_breakpoint); - - /* Reinsert all breakpoints in the child. (The user may've set - breakpoints after catching the fork, in which case those - actually didn't get set in the child, but only in the parent.) */ - breakpoint_re_set (); - insert_breakpoints (); - } - - /* The parent and child of a vfork share the same address space. - Also, on some targets the order in which vfork and exec events - are received for parent in child requires some delicate handling - of the events. - - For instance, on ptrace-based HPUX we receive the child's vfork - event first, at which time the parent has been suspended by the - OS and is essentially untouchable until the child's exit or second - exec event arrives. At that time, the parent's vfork event is - delivered to us, and that's when we see and decide how to follow - the vfork. But to get to that point, we must continue the child - until it execs or exits. To do that smoothly, all breakpoints - must be removed from the child, in case there are any set between - the vfork() and exec() calls. But removing them from the child - also removes them from the parent, due to the shared-address-space - nature of a vfork'd parent and child. On HPUX, therefore, we must - take care to restore the bp's to the parent before we continue it. - Else, it's likely that we may not stop in the expected place. (The - worst scenario is when the user tries to step over a vfork() call; - the step-resume bp must be restored for the step to properly stop - in the parent after the call completes!) - - Sequence of events, as reported to gdb from HPUX: - - Parent Child Action for gdb to take - ------------------------------------------------------- - 1 VFORK Continue child - 2 EXEC - 3 EXEC or EXIT - 4 VFORK */ - if (has_vforked) - { - target_post_follow_vfork (parent_pid, - followed_parent, child_pid, followed_child); - } - pending_follow.fork_event.saw_parent_fork = 0; pending_follow.fork_event.saw_child_fork = 0; + + return target_follow_fork (follow_child); } -static void -follow_fork (int parent_pid, int child_pid) +void +follow_inferior_reset_breakpoints (void) { - follow_inferior_fork (parent_pid, child_pid, 1, 0); -} + /* Was there a step_resume breakpoint? (There was if the user + did a "next" at the fork() call.) If so, explicitly reset its + thread number. + step_resumes are a form of bp that are made to be per-thread. + Since we created the step_resume bp when the parent process + was being debugged, and now are switching to the child process, + from the breakpoint package's viewpoint, that's a switch of + "threads". We must update the bp's notion of which thread + it is for, or it'll be ignored when it triggers. */ -/* Forward declaration. */ -static void follow_exec (int, char *); + if (step_resume_breakpoint) + breakpoint_re_set_thread (step_resume_breakpoint); -static void -follow_vfork (int parent_pid, int child_pid) -{ - follow_inferior_fork (parent_pid, child_pid, 0, 1); + /* Reinsert all breakpoints in the child. The user may have set + breakpoints after catching the fork, in which case those + were never set in the child, but only in the parent. This makes + sure the inserted breakpoints match the breakpoint list. */ + + breakpoint_re_set (); + insert_breakpoints (); } /* EXECD_PATHNAME is assumed to be non-NULL. */ @@ -722,38 +611,19 @@ resume (int step, enum target_signal sig) #endif /* If there were any forks/vforks/execs that were caught and are - now to be followed, then do so. */ + now to be followed, then do so. */ switch (pending_follow.kind) { - case (TARGET_WAITKIND_FORKED): + case TARGET_WAITKIND_FORKED: + case TARGET_WAITKIND_VFORKED: pending_follow.kind = TARGET_WAITKIND_SPURIOUS; - follow_fork (PIDGET (inferior_ptid), - pending_follow.fork_event.child_pid); + if (follow_fork ()) + should_resume = 0; break; - case (TARGET_WAITKIND_VFORKED): - { - int saw_child_exec = pending_follow.fork_event.saw_child_exec; - - pending_follow.kind = TARGET_WAITKIND_SPURIOUS; - follow_vfork (PIDGET (inferior_ptid), - pending_follow.fork_event.child_pid); - - /* Did we follow the child, but not yet see the child's exec event? - If so, then it actually ought to be waiting for us; we respond to - parent vfork events. We don't actually want to resume the child - in this situation; we want to just get its exec event. */ - if (!saw_child_exec && - (PIDGET (inferior_ptid) == pending_follow.fork_event.child_pid)) - should_resume = 0; - } - break; - - case (TARGET_WAITKIND_EXECD): - /* If we saw a vfork event but couldn't follow it until we saw - an exec, then now might be the time! */ - pending_follow.kind = TARGET_WAITKIND_SPURIOUS; + case TARGET_WAITKIND_EXECD: /* follow_exec is called as soon as the exec event is seen. */ + pending_follow.kind = TARGET_WAITKIND_SPURIOUS; break; default: diff --git a/gdb/inftarg.c b/gdb/inftarg.c index 27166db6b10..137407d4f8f 100644 --- a/gdb/inftarg.c +++ b/gdb/inftarg.c @@ -469,14 +469,12 @@ child_remove_vfork_catchpoint (int pid) } #endif -#if !defined(CHILD_POST_FOLLOW_VFORK) -void -child_post_follow_vfork (int parent_pid, int followed_parent, int child_pid, - int followed_child) +#if !defined(CHILD_FOLLOW_FORK) +int +child_follow_fork (int follow_child) { - /* This version of Unix doesn't require a meaningful "post follow vfork" - operation by a clone debugger. - */ + /* This version of Unix doesn't support following fork or vfork events. */ + return 0; } #endif @@ -645,7 +643,7 @@ init_child_ops (void) child_ops.to_remove_fork_catchpoint = child_remove_fork_catchpoint; child_ops.to_insert_vfork_catchpoint = child_insert_vfork_catchpoint; child_ops.to_remove_vfork_catchpoint = child_remove_vfork_catchpoint; - child_ops.to_post_follow_vfork = child_post_follow_vfork; + child_ops.to_follow_fork = child_follow_fork; child_ops.to_insert_exec_catchpoint = child_insert_exec_catchpoint; child_ops.to_remove_exec_catchpoint = child_remove_exec_catchpoint; child_ops.to_reported_exec_events_per_exec_call = child_reported_exec_events_per_exec_call; diff --git a/gdb/target.c b/gdb/target.c index 795468c2c85..2adea957814 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -473,8 +473,8 @@ cleanup_target (struct target_ops *t) de_fault (to_remove_vfork_catchpoint, (int (*) (int)) tcomplain); - de_fault (to_post_follow_vfork, - (void (*) (int, int, int, int)) + de_fault (to_follow_fork, + (int (*) (int)) target_ignore); de_fault (to_insert_exec_catchpoint, (int (*) (int)) @@ -597,7 +597,7 @@ update_current_target (void) INHERIT (to_remove_fork_catchpoint, t); INHERIT (to_insert_vfork_catchpoint, t); INHERIT (to_remove_vfork_catchpoint, t); - INHERIT (to_post_follow_vfork, t); + INHERIT (to_follow_fork, t); INHERIT (to_insert_exec_catchpoint, t); INHERIT (to_remove_exec_catchpoint, t); INHERIT (to_reported_exec_events_per_exec_call, t); @@ -2064,15 +2064,15 @@ debug_to_remove_vfork_catchpoint (int pid) return retval; } -static void -debug_to_post_follow_vfork (int parent_pid, int followed_parent, int child_pid, - int followed_child) +static int +debug_to_follow_fork (int follow_child) { - debug_target.to_post_follow_vfork (parent_pid, followed_parent, child_pid, followed_child); + int retval = debug_target.to_follow_fork (follow_child); - fprintf_unfiltered (gdb_stdlog, - "target_post_follow_vfork (%d, %d, %d, %d)\n", - parent_pid, followed_parent, child_pid, followed_child); + fprintf_unfiltered (gdb_stdlog, "target_follow_fork (%d) = %d\n", + follow_child, retval); + + return retval; } static int @@ -2285,7 +2285,7 @@ setup_target_debug (void) current_target.to_remove_fork_catchpoint = debug_to_remove_fork_catchpoint; current_target.to_insert_vfork_catchpoint = debug_to_insert_vfork_catchpoint; current_target.to_remove_vfork_catchpoint = debug_to_remove_vfork_catchpoint; - current_target.to_post_follow_vfork = debug_to_post_follow_vfork; + current_target.to_follow_fork = debug_to_follow_fork; current_target.to_insert_exec_catchpoint = debug_to_insert_exec_catchpoint; current_target.to_remove_exec_catchpoint = debug_to_remove_exec_catchpoint; current_target.to_reported_exec_events_per_exec_call = debug_to_reported_exec_events_per_exec_call; diff --git a/gdb/target.h b/gdb/target.h index 79c2eaa1c02..e56207de5bc 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -276,7 +276,7 @@ struct target_ops int (*to_remove_fork_catchpoint) (int); int (*to_insert_vfork_catchpoint) (int); int (*to_remove_vfork_catchpoint) (int); - void (*to_post_follow_vfork) (int, int, int, int); + int (*to_follow_fork) (int); int (*to_insert_exec_catchpoint) (int); int (*to_remove_exec_catchpoint) (int); int (*to_reported_exec_events_per_exec_call) (void); @@ -548,7 +548,7 @@ extern int child_remove_vfork_catchpoint (int); extern void child_acknowledge_created_inferior (int); -extern void child_post_follow_vfork (int, int, int, int); +extern int child_follow_fork (int); extern int child_insert_exec_catchpoint (int); @@ -705,16 +705,16 @@ extern void target_load (char *arg, int from_tty); #define target_remove_vfork_catchpoint(pid) \ (*current_target.to_remove_vfork_catchpoint) (pid) -/* An inferior process has been created via a vfork() system call. - The debugger has followed the parent, the child, or both. The - process of setting up for that follow may have required some - target-specific trickery to track the sequence of reported events. - If so, this function should be defined by those targets that - require the debugger to perform cleanup or initialization after - the vfork follow. */ +/* If the inferior forks or vforks, this function will be called at + the next resume in order to perform any bookkeeping and fiddling + necessary to continue debugging either the parent or child, as + requested, and releasing the other. Information about the fork + or vfork event is available via get_last_target_status (). + This function returns 1 if the inferior should not be resumed + (i.e. there is another event pending). */ -#define target_post_follow_vfork(parent_pid,followed_parent,child_pid,followed_child) \ - (*current_target.to_post_follow_vfork) (parent_pid,followed_parent,child_pid,followed_child) +#define target_follow_fork(follow_child) \ + (*current_target.to_follow_fork) (follow_child) /* On some targets, we can catch an inferior exec event when it occurs. These functions insert/remove an already-created diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 24c947fc641..6ae589d3660 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2002-12-10 Daniel Jacobowitz + + * gdb.base/foll-vfork.exp: Re-enable test on HP/UX. + 2002-12-06 David Carlton * gdb.base/store.c: Don't declare functions static. diff --git a/gdb/testsuite/gdb.base/foll-vfork.exp b/gdb/testsuite/gdb.base/foll-vfork.exp index 1fed06bb966..86a1ce9fcfa 100644 --- a/gdb/testsuite/gdb.base/foll-vfork.exp +++ b/gdb/testsuite/gdb.base/foll-vfork.exp @@ -28,10 +28,13 @@ if { ![isnative] } then { set prms_id 0 set bug_id 0 -if [istarget "hppa2.0w-hp-hpux*"] { - warning "Don't run gdb.base/foll-vfork.exp until JAGaa43495 kernel problem is fixed." - return 0 -} +# NOTE drow/2002-12-06: I don't know what the referenced kernel problem +# is, but it appears to be fixed in recent HP/UX versions. + +##if [istarget "hppa2.0w-hp-hpux*"] { +## warning "Don't run gdb.base/foll-vfork.exp until JAGaa43495 kernel problem is fixed." +## return 0 +##} set testfile "foll-vfork" set testfile2 "vforked-prog"