aboutsummaryrefslogtreecommitdiff
path: root/gdb/hppah-nat.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2002-12-11 02:02:03 +0000
committerDaniel Jacobowitz <drow@false.org>2002-12-11 02:02:03 +0000
commit7d2830a309f131b09372007cdff1f277a76b2458 (patch)
tree1fe0686cc6c8e079cc924466a147bb3fdf06bb88 /gdb/hppah-nat.c
parent8e7d2c16952df15b6628a9f2ee985086a408561f (diff)
downloadgdb-7d2830a309f131b09372007cdff1f277a76b2458.zip
gdb-7d2830a309f131b09372007cdff1f277a76b2458.tar.gz
gdb-7d2830a309f131b09372007cdff1f277a76b2458.tar.bz2
* hppah-nat.c (saved_child_execd_pathname, saved_vfork_state): New.
(child_post_follow_vfork): Cancel pending exec event if we follow the parent. (child_wait): Only return TARGET_WAITKIND_VFORKED when all necessary events have been processed. Return a fake TARGET_WAITKIND_EXECD event at the following wait call if necessary. * infrun.c (follow_vfork): Don't follow_exec here. (handle_inferior_event): Add comment to TARGET_WAITKIND_EXECD case about HP/UX 10.20. Remove code pushed down to hppah-nat.c:child_wait. * infttrace.c (child_resume): Use TT_PROC_CONTINUE if vfork_in_flight is set.
Diffstat (limited to 'gdb/hppah-nat.c')
-rw-r--r--gdb/hppah-nat.c92
1 files changed, 85 insertions, 7 deletions
diff --git a/gdb/hppah-nat.c b/gdb/hppah-nat.c
index 1761407..d7919e6 100644
--- a/gdb/hppah-nat.c
+++ b/gdb/hppah-nat.c
@@ -384,6 +384,14 @@ child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
return len;
}
+char *saved_child_execd_pathname = NULL;
+enum {
+ STATE_NONE,
+ STATE_GOT_CHILD,
+ STATE_GOT_EXEC,
+ STATE_GOT_PARENT,
+ STATE_FAKE_EXEC
+} saved_vfork_state = STATE_NONE;
void
child_post_follow_vfork (int parent_pid, int followed_parent, int child_pid,
@@ -410,6 +418,13 @@ child_post_follow_vfork (int parent_pid, int followed_parent, int child_pid,
reattach_breakpoints (parent_pid);
}
+ /* 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 (followed_parent || saved_vfork_state == STATE_GOT_PARENT)
+ saved_vfork_state = STATE_NONE;
+
/* 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. */
@@ -466,7 +481,6 @@ hppa_tid_to_str (ptid_t ptid)
int not_same_real_pid = 1;
/*## */
-
/* Wait for child to do something. Return pid of child, or -1 in case
of error; store status through argument pointer OURSTATUS. */
@@ -482,6 +496,14 @@ child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
enum target_waitkind kind;
int pid;
+ if (saved_vfork_state == STATE_FAKE_EXEC)
+ {
+ saved_vfork_state = STATE_NONE;
+ ourstatus->kind = TARGET_WAITKIND_EXECD;
+ ourstatus->value.execd_pathname = saved_child_execd_pathname;
+ return inferior_ptid;
+ }
+
do
{
set_sigint_trap (); /* Causes SIGINT to be passed on to the
@@ -543,17 +565,73 @@ child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
}
}
- if (hpux_has_vforked (pid, &related_pid)
- && ((pid == PIDGET (inferior_ptid))
- || (related_pid == PIDGET (inferior_ptid))))
+ if (hpux_has_vforked (pid, &related_pid))
{
- ourstatus->kind = TARGET_WAITKIND_VFORKED;
- ourstatus->value.related_pid = related_pid;
- return pid_to_ptid (pid);
+ if (pid == PIDGET (inferior_ptid))
+ {
+ if (saved_vfork_state == STATE_GOT_CHILD)
+ saved_vfork_state = STATE_GOT_PARENT;
+ else if (saved_vfork_state == STATE_GOT_EXEC)
+ saved_vfork_state = STATE_FAKE_EXEC;
+ else
+ fprintf_unfiltered (gdb_stdout,
+ "hppah: parent vfork: confused\n");
+ }
+ else if (related_pid == PIDGET (inferior_ptid))
+ {
+ if (saved_vfork_state == STATE_NONE)
+ saved_vfork_state = STATE_GOT_CHILD;
+ else
+ fprintf_unfiltered (gdb_stdout,
+ "hppah: child vfork: confused\n");
+ }
+ else
+ fprintf_unfiltered (gdb_stdout,
+ "hppah: unknown vfork: confused\n");
+
+ 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);
+ }
+ else
+ {
+ ourstatus->kind = TARGET_WAITKIND_VFORKED;
+ ourstatus->value.related_pid = related_pid;
+ 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)
+ {
+ saved_child_execd_pathname = execd_pathname;
+ 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;
+ return inferior_ptid;
+ }
+
/* Are we ignoring initial exec events? (This is likely because
we're in the process of starting up the inferior, and another
(older) mechanism handles those.) If so, we'll report this