This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: Fork event updates, part the first


I'm going to have a series of patches over the next few days to bring the
fork support back into shape.  Here's the first one.

Current status summary: These operations (fork, exec, and vfork events) are
supported under HP/UX only; fork and exec events work; vfork events, which
constitute the bulk of the unpleasant code, do not.  It appears that the
HP/UX kernel bug (?) referenced in foll-vfork.exp is still present, or that
the fixes to it sufficiently changed the interface that GDB's
vfork-following code no longer works.  Even HP's wdb debugger (it claims to
be GDB 3.0, ha ha) hangs if you step over a vfork.

I intend to preserve support for fork/exec on HP/UX; I'm testing on HP/UX 11
as I go along.  I intend to rip out any piece of the vfork support that I
notice and consider intrusive; I have the design in my head for how to
"properly" implement this feature on HP/UX, although I've no intention of
doing it myself.  In a couple of patches I'll stick an explanation of the
technique in hppah-nat.c.  If anyone else is motivated to do it I'll lend a
hand.

In three or four more I'll be ready to actually start adding the Linux
support!  (BTW: Yes, the missing GNU there was intentional... this is a
kernel feature...)

This patch removes the target target_can_follow_vfork_prior_to_exec method.
I believe it was never in the right place; it's a wart very reminiscent of
DECR_PC_AFTER_BREAK.  It should be handled completely in the target-specific
code and left entirely out of infrun.  Then I kill a bunch of dead comments
and simplify a lot of if statements based on the assumption that if the
target told us about the vfork we are prepared to follow it.

Unless there's any objection I'll commit this on Friday.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2002-11-13  Daniel Jacobowitz  <drow@mvista.com>

	* hppah-nat.c (child_can_follow_vfork_prior_to_exec): Remove.
	* inftarg.c (child_can_follow_vfork_prior_to_exec): Remove.
	(init_child_ops): Don't initialize to_can_follow_vfork_prior_to_exec.
	* infttrace.c (child_can_follow_vfork_prior_to_exec): Remove.
	* target.c (cleanup_target): Remove reference to
	to_can_follow_vfork_prior_to_exec.
	(update_current_target): Likewise.
	(debug_to_can_follow_vfork_prior_to_exec): Remove.
	(setup_target_debug): Remove reference to
	to_can_follow_vfork_prior_to_exec.
	* target.h (struct target_ops): Remove
	to_can_follow_vfork_prior_to_exec.
	(child_can_follow_vfork_prior_to_exec): Remove prototype.
	(target_can_follow_vfork_prior_to_exec): Remove definition.
	* config/pa/nm-hppah.h (CHILD_CAN_FOLLOW_VFORK_PRIOR_TO_EXEC): Don't
	define.
	* infrun.c (follow_vfork_when_exec): Remove.
	(follow_inferior_fork): Remove references to follow_vfork_when_exec.
	(follow_exec): Likewise.
	(handle_inferior_event): Likewise.
	(keep_going): Likewise.

diff -urp gdb.clean/config/pa/nm-hppah.h gdb.work1/config/pa/nm-hppah.h
--- gdb.clean/config/pa/nm-hppah.h	2002-10-14 16:42:25.000000000 -0400
+++ gdb.work1/config/pa/nm-hppah.h	2002-11-13 16:18:27.000000000 -0500
@@ -83,7 +83,6 @@ extern int hppa_prepare_to_proceed (void
 #define CHILD_REMOVE_VFORK_CATCHPOINT
 #define CHILD_HAS_FORKED
 #define CHILD_HAS_VFORKED
-#define CHILD_CAN_FOLLOW_VFORK_PRIOR_TO_EXEC
 #define CHILD_INSERT_EXEC_CATCHPOINT
 #define CHILD_REMOVE_EXEC_CATCHPOINT
 #define CHILD_HAS_EXECD
diff -urp gdb.clean/hppah-nat.c gdb.work1/hppah-nat.c
--- gdb.clean/hppah-nat.c	2001-10-27 20:16:00.000000000 -0400
+++ gdb.work1/hppah-nat.c	2002-11-12 18:58:49.000000000 -0500
@@ -953,13 +953,6 @@ child_has_vforked (int pid, int *childpi
 }
 
 int
-child_can_follow_vfork_prior_to_exec (void)
-{
-  /* ptrace doesn't allow this. */
-  return 0;
-}
-
-int
 child_insert_exec_catchpoint (int pid)
 {
   /* This request is only available on HPUX 10.0 and later.   */
diff -urp gdb.clean/infrun.c gdb.work1/infrun.c
--- gdb.clean/infrun.c	2002-10-30 16:55:01.000000000 -0500
+++ gdb.work1/infrun.c	2002-11-12 18:57:11.000000000 -0500
@@ -370,21 +370,6 @@ static struct
 }
 pending_follow;
 
-/* Some platforms don't allow us to do anything meaningful with a
-   vforked child until it has exec'd.  Vforked processes on such
-   platforms can only be followed after they've exec'd.
-
-   When this is set to 0, a vfork can be immediately followed,
-   and an exec can be followed merely as an exec.  When this is
-   set to 1, a vfork event has been seen, but cannot be followed
-   until the exec is seen.
-
-   (In the latter case, inferior_ptid is still the parent of the
-   vfork, and pending_follow.fork_event.child_pid is the child.  The
-   appropriate process is followed, according to the setting of
-   follow-fork-mode.) */
-static int follow_vfork_when_exec;
-
 static const char follow_fork_mode_ask[] = "ask";
 static const char follow_fork_mode_both[] = "both";
 static const char follow_fork_mode_child[] = "child";
@@ -435,13 +420,10 @@ follow_inferior_fork (int parent_pid, in
       /* 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.) */
-      if (!has_vforked || !follow_vfork_when_exec)
-	{
-	  detach_breakpoints (child_pid);
+      detach_breakpoints (child_pid);
 #ifdef SOLIB_REMOVE_INFERIOR_HOOK
-	  SOLIB_REMOVE_INFERIOR_HOOK (child_pid);
+      SOLIB_REMOVE_INFERIOR_HOOK (child_pid);
 #endif
-	}
 
       /* Detach from the child. */
       dont_repeat ();
@@ -458,15 +440,10 @@ follow_inferior_fork (int parent_pid, in
       followed_child = 1;
 
       /* Before detaching from the parent, detach all breakpoints from
-         the child.  But only if we're forking, or if we follow vforks
-         as soon as they happen.  (If we're following vforks only when
-         the child has exec'd, then it's very wrong to try to write
-         back the "shadow contents" of inserted breakpoints now -- they
-         belong to the child's pre-exec'd a.out.) */
-      if (!has_vforked || !follow_vfork_when_exec)
-	{
-	  detach_breakpoints (child_pid);
-	}
+         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 ();
@@ -497,17 +474,16 @@ follow_inferior_fork (int parent_pid, in
          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... */
-      if (step_resume_breakpoint && (!has_vforked || !follow_vfork_when_exec))
+      /* 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.) */
-      if (!has_vforked || !follow_vfork_when_exec)
-	{
-	  breakpoint_re_set ();
-	  insert_breakpoints ();
-	}
+      breakpoint_re_set ();
+      insert_breakpoints ();
     }
 
   /* If we're to be following both parent and child, then fork ourselves,
@@ -605,23 +581,6 @@ follow_exec (int pid, char *execd_pathna
   if (!may_follow_exec)
     return;
 
-  /* Did this exec() follow a vfork()?  If so, we must follow the
-     vfork now too.  Do it before following the exec. */
-  if (follow_vfork_when_exec &&
-      (pending_follow.kind == TARGET_WAITKIND_VFORKED))
-    {
-      pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
-      follow_vfork (PIDGET (inferior_ptid),
-		    pending_follow.fork_event.child_pid);
-      follow_vfork_when_exec = 0;
-      saved_pid = PIDGET (inferior_ptid);
-
-      /* Did we follow the parent?  If so, we're done.  If we followed
-         the child then we must also follow its exec(). */
-      if (PIDGET (inferior_ptid) == pending_follow.fork_event.parent_pid)
-	return;
-    }
-
   /* This is an exec event that we actually wish to pay attention to.
      Refresh our symbol table to the newly exec'd program, remove any
      momentary bp's, etc.
@@ -1615,13 +1574,6 @@ handle_inferior_event (struct execution_
 	  target_post_startup_inferior (pid_to_ptid
 					(pending_follow.fork_event.
 					 child_pid));
-	  follow_vfork_when_exec = !target_can_follow_vfork_prior_to_exec ();
-	  if (follow_vfork_when_exec)
-	    {
-	      target_resume (ecs->ptid, 0, TARGET_SIGNAL_0);
-	      prepare_to_wait (ecs);
-	      return;
-	    }
 	}
 
       stop_pc = read_pc ();
@@ -3114,16 +3066,6 @@ stop_stepping (struct execution_control_
 static void
 keep_going (struct execution_control_state *ecs)
 {
-  /* ??rehrauer: ttrace on HP-UX theoretically allows one to debug a
-     vforked child between its creation and subsequent exit or call to
-     exec().  However, I had big problems in this rather creaky exec
-     engine, getting that to work.  The fundamental problem is that
-     I'm trying to debug two processes via an engine that only
-     understands a single process with possibly multiple threads.
-
-     Hence, this spot is known to have problems when
-     target_can_follow_vfork_prior_to_exec returns 1. */
-
   /* Save the pc before execution, to compare with pc after stop.  */
   prev_pc = read_pc ();		/* Might have been DECR_AFTER_BREAK */
   prev_func_start = ecs->stop_func_start;	/* Ok, since if DECR_PC_AFTER
diff -urp gdb.clean/inftarg.c gdb.work1/inftarg.c
--- gdb.clean/inftarg.c	2002-08-29 15:08:05.000000000 -0400
+++ gdb.work1/inftarg.c	2002-11-12 18:58:16.000000000 -0500
@@ -573,19 +573,6 @@ child_has_vforked (int pid, int *child_p
 #endif
 
 
-#if !defined(CHILD_CAN_FOLLOW_VFORK_PRIOR_TO_EXEC)
-int
-child_can_follow_vfork_prior_to_exec (void)
-{
-  /* This version of Unix doesn't support notification of vfork events.
-     However, if it did, it probably wouldn't allow vforks to be followed
-     before the following exec.
-   */
-  return 0;
-}
-#endif
-
-
 #if !defined(CHILD_POST_FOLLOW_VFORK)
 void
 child_post_follow_vfork (int parent_pid, int followed_parent, int child_pid,
@@ -789,7 +776,6 @@ init_child_ops (void)
   child_ops.to_remove_vfork_catchpoint = child_remove_vfork_catchpoint;
   child_ops.to_has_forked = child_has_forked;
   child_ops.to_has_vforked = child_has_vforked;
-  child_ops.to_can_follow_vfork_prior_to_exec = child_can_follow_vfork_prior_to_exec;
   child_ops.to_post_follow_vfork = child_post_follow_vfork;
   child_ops.to_insert_exec_catchpoint = child_insert_exec_catchpoint;
   child_ops.to_remove_exec_catchpoint = child_remove_exec_catchpoint;
diff -urp gdb.clean/infttrace.c gdb.work1/infttrace.c
--- gdb.clean/infttrace.c	2002-09-13 18:54:37.000000000 -0400
+++ gdb.work1/infttrace.c	2002-11-12 18:57:42.000000000 -0500
@@ -3449,21 +3449,6 @@ child_has_vforked (int tid, int *childpi
 #endif
 
 
-#if defined(CHILD_CAN_FOLLOW_VFORK_PRIOR_TO_EXEC)
-int
-child_can_follow_vfork_prior_to_exec (void)
-{
-  /* ttrace does allow this.
-
-     ??rehrauer: However, I had major-league problems trying to
-     convince wait_for_inferior to handle that case.  Perhaps when
-     it is rewritten to grok multiple processes in an explicit way...
-   */
-  return 0;
-}
-#endif
-
-
 #if defined(CHILD_INSERT_EXEC_CATCHPOINT)
 int
 child_insert_exec_catchpoint (int tid)
diff -urp gdb.clean/target.c gdb.work1/target.c
--- gdb.clean/target.c	2002-11-12 16:43:17.000000000 -0500
+++ gdb.work1/target.c	2002-11-12 18:59:23.000000000 -0500
@@ -492,9 +492,6 @@ cleanup_target (struct target_ops *t)
   de_fault (to_has_vforked, 
 	    (int (*) (int, int *)) 
 	    return_zero);
-  de_fault (to_can_follow_vfork_prior_to_exec, 
-	    (int (*) (void)) 
-	    return_zero);
   de_fault (to_post_follow_vfork, 
 	    (void (*) (int, int, int, int)) 
 	    target_ignore);
@@ -629,7 +626,6 @@ update_current_target (void)
       INHERIT (to_remove_vfork_catchpoint, t);
       INHERIT (to_has_forked, t);
       INHERIT (to_has_vforked, t);
-      INHERIT (to_can_follow_vfork_prior_to_exec, t);
       INHERIT (to_post_follow_vfork, t);
       INHERIT (to_insert_exec_catchpoint, t);
       INHERIT (to_remove_exec_catchpoint, t);
@@ -2154,19 +2150,6 @@ debug_to_has_vforked (int pid, int *chil
   return has_vforked;
 }
 
-static int
-debug_to_can_follow_vfork_prior_to_exec (void)
-{
-  int can_immediately_follow_vfork;
-
-  can_immediately_follow_vfork = debug_target.to_can_follow_vfork_prior_to_exec ();
-
-  fprintf_unfiltered (gdb_stdlog, "target_can_follow_vfork_prior_to_exec () = %d\n",
-		      can_immediately_follow_vfork);
-
-  return can_immediately_follow_vfork;
-}
-
 static void
 debug_to_post_follow_vfork (int parent_pid, int followed_parent, int child_pid,
 			    int followed_child)
@@ -2436,7 +2419,6 @@ setup_target_debug (void)
   current_target.to_remove_vfork_catchpoint = debug_to_remove_vfork_catchpoint;
   current_target.to_has_forked = debug_to_has_forked;
   current_target.to_has_vforked = debug_to_has_vforked;
-  current_target.to_can_follow_vfork_prior_to_exec = debug_to_can_follow_vfork_prior_to_exec;
   current_target.to_post_follow_vfork = debug_to_post_follow_vfork;
   current_target.to_insert_exec_catchpoint = debug_to_insert_exec_catchpoint;
   current_target.to_remove_exec_catchpoint = debug_to_remove_exec_catchpoint;
diff -urp gdb.clean/target.h gdb.work1/target.h
--- gdb.clean/target.h	2002-11-12 16:43:17.000000000 -0500
+++ gdb.work1/target.h	2002-11-12 18:58:35.000000000 -0500
@@ -280,7 +280,6 @@ struct target_ops
     int (*to_remove_vfork_catchpoint) (int);
     int (*to_has_forked) (int, int *);
     int (*to_has_vforked) (int, int *);
-    int (*to_can_follow_vfork_prior_to_exec) (void);
     void (*to_post_follow_vfork) (int, int, int, int);
     int (*to_insert_exec_catchpoint) (int);
     int (*to_remove_exec_catchpoint) (int);
@@ -563,8 +562,6 @@ extern int child_has_vforked (int, int *
 
 extern void child_acknowledge_created_inferior (int);
 
-extern int child_can_follow_vfork_prior_to_exec (void);
-
 extern void child_post_follow_vfork (int, int, int, int);
 
 extern int child_insert_exec_catchpoint (int);
@@ -759,18 +756,6 @@ extern void target_load (char *arg, int 
 #define target_has_vforked(pid,child_pid) \
      (*current_target.to_has_vforked) (pid,child_pid)
 
-/* Some platforms (such as pre-10.20 HP-UX) don't allow us to do
-   anything to a vforked child before it subsequently calls exec().
-   On such platforms, we say that the debugger cannot "follow" the
-   child until it has vforked.
-
-   This function should be defined to return 1 by those targets
-   which can allow the debugger to immediately follow a vforked
-   child, and 0 if they cannot.  */
-
-#define target_can_follow_vfork_prior_to_exec() \
-     (*current_target.to_can_follow_vfork_prior_to_exec) ()
-
 /* 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]