This is the mail archive of the 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]

[commit] [2/3] watchpoints across vfork regressions - software watchpoints

While writing a testcase for the previous patch, I
remembered to try the same thing, but with a software watchpoint,
instead of a hardware one, and, that exposed another regression.

The regression relates to this bit in handle_inferior_event:

      ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat);

      /* If no catchpoint triggered for this, then keep going.  */
      if (ecs->random_signal)
        ... follow fork (resume parent, detach child, etc...)

random_signal ended up false, because the software watchpoint ends up
in the bpstat (with bpstat->stop false) and so we'd handle the
event as if a catchpoint had triggered, but, it didn't.  While
the bpstat indeed explains the signal, it isn't causing
a stop.  handle_inferior_event would then decide the event
thread wasn't even stepping, so kept it going (resumed the
vfork parent).  Problem is, nothing 'follows' the fork in that
code path (that is, nothing resumes the child), and so, the
vfork parent remains frozen (by the kernel) forever waiting for
the child to exec or exit.  Result, GDB hangs.

I've applied this fix.  Patch 3 adds a test that also covers this.

Pedro Alves

2009-11-15  Pedro Alves  <>

	* infrun.c (handle_inferior_event): When handling a fork or vfork
	event, check if the bpstat causes a stop, instead of if it
	explains the signal.
	* breakpoint.c (bpstat_causes_stop): New.
	* breakpoint.h (bpstat_causes_stop): Declare.

 gdb/breakpoint.c |   10 ++++++++++
 gdb/breakpoint.h |    3 +++
 gdb/infrun.c     |    6 +++++-
 3 files changed, 18 insertions(+), 1 deletion(-)

Index: src/gdb/infrun.c
--- src.orig/gdb/infrun.c	2009-11-15 19:47:13.000000000 +0000
+++ src/gdb/infrun.c	2009-11-15 19:56:52.000000000 +0000
@@ -2946,7 +2946,11 @@ handle_inferior_event (struct execution_
 	= bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
 			      stop_pc, ecs->ptid);
-      ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat);
+      /* Note that we're interested in knowing the bpstat actually
+	 causes a stop, not just if it may explain the signal.
+	 Software watchpoints, for example, always appear in the
+	 bpstat.  */
+      ecs->random_signal = !bpstat_causes_stop (ecs->event_thread->stop_bpstat);
       /* If no catchpoint triggered for this, then keep going.  */
       if (ecs->random_signal)
Index: src/gdb/breakpoint.c
--- src.orig/gdb/breakpoint.c	2009-11-15 19:47:13.000000000 +0000
+++ src/gdb/breakpoint.c	2009-11-15 19:50:28.000000000 +0000
@@ -3816,6 +3816,16 @@ bpstat_should_step (void)
   return 0;
+bpstat_causes_stop (bpstat bs)
+  for (; bs != NULL; bs = bs->next)
+    if (bs->stop)
+      return 1;
+  return 0;
 static void print_breakpoint_location (struct breakpoint *b,
Index: src/gdb/breakpoint.h
--- src.orig/gdb/breakpoint.h	2009-11-15 19:45:33.000000000 +0000
+++ src/gdb/breakpoint.h	2009-11-15 19:50:28.000000000 +0000
@@ -629,6 +629,9 @@ extern struct breakpoint *bpstat_find_st
    a watchpoint enabled.  */
 #define bpstat_explains_signal(bs) ((bs) != NULL)
+/* Nonzero is this bpstat causes a stop.  */
+extern int bpstat_causes_stop (bpstat);
 /* Nonzero if we should step constantly (e.g. watchpoints on machines
    without hardware support).  This isn't related to a specific bpstat,
    just to things like whether watchpoints are set.  */

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