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]

[intercu] Use cleanups properly


This removes a couple of FIXMEs by adding appropriate cleanup functions, and
either doing or discarding them on success.  The only memory leak plugged in
the non-error case was releasing the dwarf2_tmp_obstack, which got lost in
the shuffle.

Committed to the intercu branch.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2004-02-24  Daniel Jacobowitz  <drow@mvista.com>

	* dwarf2read.c (free_one_comp_unit): Update signature so it can be
	used as a cleanup.  Clear the per_cu pointer.  Add some comments.
	(free_one_cached_comp_unit): Update signature so it can be used
	as a cleanup.  Remove unused argument.
	(dwarf2_build_psymtabs_hard): Update call to
	free_one_cached_comp_unit.  Don't free the obstack here.
	(process_queue): Keep dwarf2_queue up to date as we remove items
	from the queue.
	(dwarf2_release_queue): New function.
	(psymtab_to_symtab_1): Use cleanups.
	(load_full_comp_unit): Likewise.
	(free_comp_units_worker): Remove clearing of the cu pointer.
	(clear_per_cu_pointer): Also free the partial_die_obstack.  Update
	comments.

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.135.2.31
diff -u -p -r1.135.2.31 dwarf2read.c
--- dwarf2read.c	24 Feb 2004 03:27:21 -0000	1.135.2.31
+++ dwarf2read.c	25 Feb 2004 00:01:53 -0000
@@ -987,7 +987,7 @@ static struct dwarf2_per_cu_data *dwarf2
 static struct partial_symtab *dwarf2_find_comp_unit_psymtab
   (unsigned int offset, struct objfile *objfile);
 
-static void free_one_comp_unit (struct dwarf2_cu *);
+static void free_one_comp_unit (void *);
 
 static void clear_per_cu_pointer (void *);
 
@@ -995,7 +995,7 @@ static void free_cached_comp_units (void
 
 static void age_cached_comp_units (void *);
 
-static void free_one_cached_comp_unit (struct dwarf2_cu *, struct dwarf2_cu *);
+static void free_one_cached_comp_unit (void *);
 
 static void set_die_type (struct die_info *, struct type *,
 			  struct dwarf2_cu *);
@@ -1446,7 +1446,7 @@ dwarf2_build_psymtabs_hard (struct objfi
 	     a nice speed boost but require a lot of editing in this
 	     function.  */
 	  if (per_cu->cu != NULL)
-	    free_one_cached_comp_unit (&cu, per_cu->cu);
+	    free_one_cached_comp_unit (per_cu->cu);
 
 	  cu.per_cu = per_cu;
 
@@ -1486,9 +1486,6 @@ dwarf2_build_psymtabs_hard (struct objfi
 
 	  scan_partial_symbols (first_die, &lowpc, &highpc, &cu, 0);
 
-	  cu.partial_dies = NULL;
-	  obstack_free (&cu.partial_die_obstack, NULL);
-
 	  /* If we didn't find a lowpc, set it to highpc to avoid
 	     complaints from `maint check'.  */
 	  if (lowpc == ((CORE_ADDR) -1))
@@ -2346,6 +2343,33 @@ process_queue (struct objfile *objfile)
 	  item->per_cu->queued = 0;
 	}
       last = item;
+      dwarf2_queue = item = last->next;
+      xfree (last);
+    }
+}
+
+/* Free all allocated queue entries.  This function only releases anything if
+   an error was thrown; if the queue was processed then it would have been
+   freed as we went along.  */
+
+static void
+dwarf2_release_queue (void *dummy)
+{
+  struct dwarf2_queue_item *item, *last;
+
+  item = dwarf2_queue;
+  while (item)
+    {
+      /* Anything still marked queued is likely to be in an
+	 inconsistent state, so discard it.  */
+      if (item->per_cu->queued)
+	{
+	  if (item->per_cu->cu != NULL)
+	    free_one_cached_comp_unit (item->per_cu->cu);
+	  item->per_cu->queued = 0;
+	}
+
+      last = item;
       item = item->next;
       xfree (last);
     }
@@ -2361,13 +2385,12 @@ psymtab_to_symtab_1 (struct partial_symt
   obstack_init (&dwarf2_tmp_obstack);
   back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
 
-  /* FIXME: More cleanup issues.  */
   if (dwarf2_per_objfile->cu_tree == NULL)
     {
       struct dwarf2_cu *cu;
       cu = load_full_comp_unit (pst, NULL);
+      make_cleanup (free_one_comp_unit, cu);
       process_full_comp_unit (pst, cu);
-      free_one_comp_unit (cu);
     }
   else
     {
@@ -2381,6 +2404,9 @@ psymtab_to_symtab_1 (struct partial_symt
       per_cu = (struct dwarf2_per_cu_data *) node->value;
 
       per_cu->psymtab = pst;
+
+      make_cleanup (dwarf2_release_queue, NULL);
+
       queue_comp_unit (per_cu);
 
       process_queue (pst->objfile);
@@ -2390,9 +2416,10 @@ psymtab_to_symtab_1 (struct partial_symt
          caching.  */
       age_cached_comp_units (NULL);
     }
+
+  do_cleanups (back_to);
 }
 
-/* FIXME: Cleanup issues.  */
 static struct dwarf2_cu *
 load_full_comp_unit (struct partial_symtab *pst,
 		     struct dwarf2_per_cu_data *per_cu)
@@ -2401,7 +2428,7 @@ load_full_comp_unit (struct partial_symt
   struct dwarf2_cu *cu;
   unsigned long offset;
   char *info_ptr;
-  struct cleanup *back_to;
+  struct cleanup *back_to, *free_cu_cleanup;
   struct attribute *attr;
 
   /* Set local variables from the partial symbol table info.  */
@@ -2412,6 +2439,9 @@ load_full_comp_unit (struct partial_symt
   cu = xmalloc (sizeof (struct dwarf2_cu));
   memset (cu, 0, sizeof (struct dwarf2_cu));
 
+  /* If an error occurs while loading, release our storage.  */
+  free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
+
   cu->objfile = pst->objfile;
 
   /* read in the comp_unit header  */
@@ -2444,6 +2474,10 @@ load_full_comp_unit (struct partial_symt
 
   do_cleanups (back_to);
 
+  /* We've successfully allocated this compilation unit.  Let our caller
+     clean it up when finished with it.  */
+  discard_cleanups (free_cu_cleanup);
+
   return cu;
 }
 
@@ -9095,14 +9129,23 @@ dwarf2_find_comp_unit_psymtab (unsigned 
 		  offset);
 }
 
-/* Release one cached compilation unit, CU.  */
+/* Release one cached compilation unit, CU.  We unlink it from the tree
+   of compilation units, but we don't remove it from the read_in_chain
+   (so it should not be on that chain to begin with).  */
 
 static void
-free_one_comp_unit (struct dwarf2_cu *cu)
+free_one_comp_unit (void *data)
 {
+  struct dwarf2_cu *cu = data;
+
+  if (cu->per_cu != NULL)
+    cu->per_cu->cu = NULL;
+  cu->per_cu = NULL;
+
   obstack_free (&cu->partial_die_obstack, NULL);
   if (cu->dies)
     free_die_list (cu->dies);
+
   xfree (cu);
 }
 
@@ -9143,7 +9186,6 @@ free_comp_units_worker (struct dwarf2_cu
 	  || (!aging && target_cu == NULL))
 	{
 	  free_one_comp_unit (per_cu->cu);
-	  per_cu->cu = NULL;
 	  *last_chain = next_cu;
 	}
       else
@@ -9156,6 +9198,13 @@ free_comp_units_worker (struct dwarf2_cu
     }
 }
 
+/* This cleanup function is passed the address of a dwarf2_cu on the stack
+   when we're finished with it.  We can't free the pointer itself, but be
+   sure to unlink it from the cache.  Also release any associated storage
+   and perform cache maintenance.
+
+   Only used during partial symbol parsing.  */
+
 static void
 clear_per_cu_pointer (void *data)
 {
@@ -9163,12 +9212,15 @@ clear_per_cu_pointer (void *data)
 
   if (cu->per_cu != NULL)
     {
-      age_cached_comp_units (NULL);
+      obstack_free (&cu->partial_die_obstack, NULL);
+      cu->partial_dies = NULL;
 
       /* This compilation unit is on the stack in our caller, so we
 	 should not xfree it.  Just unlink it.  */
       cu->per_cu->cu = NULL;
       cu->per_cu = NULL;
+
+      age_cached_comp_units (NULL);
     }
 }
 
@@ -9185,7 +9237,7 @@ age_cached_comp_units (void *data)
 }
 
 static void
-free_one_cached_comp_unit (struct dwarf2_cu *cu, struct dwarf2_cu *target_cu)
+free_one_cached_comp_unit (void *target_cu)
 {
   free_comp_units_worker (target_cu, 0);
 }


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