Wireshark-dev: Re: [Wireshark-dev] ep_ memory is not garbage collected
From: Jakub Zawadzki <darkjames-ws@xxxxxxxxxxxx>
Date: Fri, 17 Aug 2012 16:02:04 +0200
On Thu, Aug 16, 2012 at 08:54:54PM -0400, Evan Huus wrote:
> On Wed, Aug 15, 2012 at 11:36 AM, Jakub Zawadzki <darkjames-ws@xxxxxxxxxxxx> wrote:
> > From r43188 sequence of selecting new packet (cf_select_packet() in file.c) is:
> >    cf_read_frame()
> >    old_edt = cf->edt;
> >    cf->edt = epan_dissect_new()                ; edt_refs++
> >    epan_dissect_run(cf->edt, ...)
> >    if (old_edt)
> >      epan_dissect_free(old_edt);               ; edt_refs--  (edt_refs != 0, no gc)
> >
> > Old code was doing something like:
> >    cf_read_frame()
> >    epan_dissect_free(cf->edt);               ; edt_refs--    (likely edt_refs == 0, gc ep memory)
> >    cf->edt = epan_dissect_new()              ; edt_refs++
> >
> > I have working fix for this, but check below.
> 
> Based on the log for r43188 I expect there's someway to force clear
> the GtkTreeStore, so that old_edt can be unrefed (triggering a gc)
> before cf->edt is re-allocated?
> 
> Is your fix checked in or attached to a bug somewhere?

Attached, but it's more workaround than fix.
diff --git a/file.c b/file.c
index 2d3b96b..8a755b7 100644
--- a/file.c
+++ b/file.c
@@ -3829,7 +3829,7 @@ cf_goto_framenum(capture_file *cf)
 void
 cf_select_packet(capture_file *cf, int row)
 {
-  epan_dissect_t *old_edt;
+  proto_tree     *old_tree = NULL;
   frame_data     *fdata;
 
   /* Get the frame data struct pointer for this frame */
@@ -3880,7 +3880,12 @@ cf_select_packet(capture_file *cf, int row)
   cf->current_frame = fdata;
   cf->current_row = row;
 
-  old_edt = cf->edt;
+  if (cf->edt) {
+    old_tree = cf->edt->tree;
+    cf->edt->tree = NULL;
+    epan_dissect_cleanup(cf->edt);
+  }
+
   /* Create the logical protocol tree. */
   /* We don't need the columns here. */
   cf->edt = epan_dissect_new(TRUE, TRUE);
@@ -3893,8 +3898,8 @@ cf_select_packet(capture_file *cf, int row)
 
   cf_callback_invoke(cf_cb_packet_selected, cf);
 
-  if (old_edt != NULL)
-    epan_dissect_free(old_edt);
+  if (old_tree != NULL)
+    proto_tree_free(old_tree);
 
 }