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.
+2002-12-10 Daniel Jacobowitz <drow@mvista.com>
+
+ * 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 <drow@mvista.com>
* hppah-nat.c (saved_child_execd_pathname, saved_vfork_state): New.
/* 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: */
}
char *saved_child_execd_pathname = NULL;
+int saved_vfork_pid;
enum {
STATE_NONE,
STATE_GOT_CHILD,
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
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))
/* 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;
}
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);
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);
static const char *follow_fork_mode_string = follow_fork_mode_parent;
\f
-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)
/* 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. */
#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:
}
#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
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;
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))
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);
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
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;
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);
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);
#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
+2002-12-10 Daniel Jacobowitz <drow@mvista.com>
+
+ * gdb.base/foll-vfork.exp: Re-enable test on HP/UX.
+
2002-12-06 David Carlton <carlton@math.stanford.edu>
* gdb.base/store.c: Don't declare functions static.
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"