This is the mail archive of the gdb-patches@sourceware.org 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] [1/3] watchpoints across vfork regressions - failed insertion detection


This fixes a regression Daniel noticed:

 $ ./gdb ./gdb
 ...
 (top-gdb) start
 Temporary breakpoint 3 at 0x454627: file ../../src/gdb/gdb.c, line 28.
 Starting program: /home/pedro/gdb/baseline/build/gdb/gdb
 [Thread debugging using libthread_db enabled]

 Temporary breakpoint 3, main (argc=
 During symbol reading, incomplete CFI data; unspecified registers (e.g., rax) at 0x45461c.
 1, argv=0x7fffffffe398) at ../../src/gdb/gdb.c:28
 28        memset (&args, 0, sizeof args);
 (top-gdb) watch selected_frame
 During symbol reading, DW_AT_name missing from DW_TAG_base_type.
 During symbol reading, unsupported tag: 'DW_TAG_const_type'.
 During symbol reading, debug info gives in-file macro definition with zero line 0: __STDC__ 1.
 Hardware watchpoint 4: selected_frame
 (top-gdb) c
 Continuing.
 Warning:
 Could not insert hardware watchpoint 4.
 Could not insert hardware breakpoints:
 You may have requested too many hardware breakpoints/watchpoints.

 0x00007ffff6cb0ee4 in vfork () from /lib/libc.so.6
 (top-gdb)     

The vfork comes from find_charset_names -> pex_run

The watchpoint wasn't inserted, because waiting_for_vfork_done
is set on the parent, but, the code that checks for
failed-to-insert-watchpoints wasn't aware of the skipping.

I've checked it in.  Patch 3/3 is a new test that covers
this use case.

Committed.

-- 
Pedro Alves

2009-11-15  Pedro Alves  <pedro@codesourcery.com>

	gdb/
	* breakpoint.c (should_be_inserted): Don't insert breakpoints if
	the pspace doesn't allow breakpoints.
	(insert_breakpoint_locations): Remove waiting_for_vfork_done
	special case.  Expect watchpoints that shouldn't be inserted, to
	not be inserted.
	* progspace.h (struct program_space) <breakpoints_not_allowed>:
	New field.
	* infrun.c (handle_inferior_event): Clear it.
	* linux-nat.c (linux_child_follow_fork): Set it.

---
 gdb/breakpoint.c |   32 ++++++++++++--------------------
 gdb/infrun.c     |    1 +
 gdb/linux-nat.c  |    1 +
 gdb/progspace.h  |    4 ++++
 4 files changed, 18 insertions(+), 20 deletions(-)

Index: src/gdb/breakpoint.c
===================================================================
--- src.orig/gdb/breakpoint.c	2009-11-15 19:45:34.000000000 +0000
+++ src/gdb/breakpoint.c	2009-11-15 19:46:32.000000000 +0000
@@ -1193,6 +1193,17 @@ should_be_inserted (struct bp_location *
   if (!bpt->enabled || bpt->shlib_disabled || bpt->duplicate)
     return 0;
 
+  /* This is set for example, when we're attached to the parent of a
+     vfork, and have detached from the child.  The child is running
+     free, and we expect it to do an exec or exit, at which point the
+     OS makes the parent schedulable again (and the target reports
+     that the vfork is done).  Until the child is done with the shared
+     memory region, do not insert breakpoints in the parent, otherwise
+     the child could still trip on the parent's breakpoints.  Since
+     the parent is blocked anyway, it won't miss any breakpoint.  */
+  if (bpt->pspace->breakpoints_not_allowed)
+    return 0;
+
   /* Tracepoints are inserted by the target at a time of its choosing,
      not by us.  */
   if (bpt->owner->type == bp_tracepoint)
@@ -1530,25 +1541,6 @@ insert_breakpoint_locations (void)
 	  && ptid_equal (inferior_ptid, null_ptid))
 	continue;
 
-      if (!ptid_equal (inferior_ptid, null_ptid))
-	{
-	  struct inferior *inf = current_inferior ();
-	  if (inf->waiting_for_vfork_done)
-	    {
-	      /* This is set when we're attached to the parent of the
-		 vfork, and have detached from the child.  The child
-		 is running free, and we expect it to do an exec or
-		 exit, at which point the OS makes the parent
-		 schedulable again (and the target reports that the
-		 vfork is done).  Until the child is done with the
-		 shared memory region, do not insert breakpoints in
-		 parent, otherwise the child could still trip on the
-		 parent's breakpoints.  Since the parent is blocked
-		 anyway, it won't miss any breakpoint.  */
-	      continue;
-	    }
-	}
-
       val = insert_bp_location (b, tmp_error_stream,
 				    &disabled_breaks,
 				    &hw_breakpoint_error);
@@ -1573,7 +1565,7 @@ insert_breakpoint_locations (void)
 	continue;
       
       for (loc = bpt->loc; loc; loc = loc->next)
-	if (!loc->inserted)
+	if (!loc->inserted && should_be_inserted (loc))
 	  {
 	    some_failed = 1;
 	    break;
Index: src/gdb/progspace.h
===================================================================
--- src.orig/gdb/progspace.h	2009-11-15 19:45:34.000000000 +0000
+++ src/gdb/progspace.h	2009-11-15 19:45:53.000000000 +0000
@@ -165,6 +165,10 @@ struct program_space
        to set breakpoints point at the wrong addresses.  */
     int executing_startup;
 
+    /* True if no breakpoints should be inserted in this program
+       space.  */
+    int breakpoints_not_allowed;
+
     /* The object file that the main symbol table was loaded from
        (e.g. the argument to the "symbol-file" or "file" command).  */
     struct objfile *symfile_object_file;
Index: src/gdb/infrun.c
===================================================================
--- src.orig/gdb/infrun.c	2009-11-15 19:45:34.000000000 +0000
+++ src/gdb/infrun.c	2009-11-15 19:45:53.000000000 +0000
@@ -3004,6 +3004,7 @@ handle_inferior_event (struct execution_
 	context_switch (ecs->ptid);
 
       current_inferior ()->waiting_for_vfork_done = 0;
+      current_inferior ()->pspace->breakpoints_not_allowed = 0;
       /* This also takes care of reinserting breakpoints in the
 	 previously locked inferior.  */
       keep_going (ecs);
Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c	2009-11-15 19:45:34.000000000 +0000
+++ src/gdb/linux-nat.c	2009-11-15 19:45:53.000000000 +0000
@@ -793,6 +793,7 @@ holding the child stopped.  Try \"set de
 	     subsequent child exec or exit is enough to know when does
 	     the child stops using the parent's address space.  */
 	  parent_inf->waiting_for_vfork_done = detach_fork;
+	  parent_inf->pspace->breakpoints_not_allowed = detach_fork;
 
 	  lp = find_lwp_pid (pid_to_ptid (parent_pid));
 	  gdb_assert (linux_supports_tracefork_flag >= 0);


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