[Gnucash-changes] Eliminate a double free of memory.
Chris Shoemaker
c.shoemaker at cox.net
Thu Jun 2 22:00:24 EDT 2005
On Thu, Jun 02, 2005 at 05:29:06PM -0400, David Hampton wrote:
> On Thu, 2005-06-02 at 16:59 -0400, Chris Shoemaker wrote:
> > 1) The gtk_destroy signal handler (gnc_customer_window_destroy_cb) does
> > NOT emit the CM event.
> > (It should be calling gnc_close_gui_component(cw->component_id);)
> >
> > 2) The CM destroy handler (gnc_customer_window_close_handler) does NOT
> > destroy the dialog context. Instead, that's actually done inside the
> > gtk_destroy signal handler.
> >
> >
> > The biggest hint that this is an abuse of the CM api is the fact that
> > the close handler is not explicitly unregistering the component with
> > the CM, instead relying on it happening as a side-effect of the
> > gtk_destroy signal. If the close handler wanted to do anything with
> > the component after it destroyed the dialog (like, say, read the
> > non-gui state) it would be screwed because the whole component has
> > been freed!
> >
> > I think all the confusion goes away when you do something like this:
> > [warning: not even compile tested]
> >
> > // This is the gtk_destroy signal handler
> > void
> > gnc_customer_window_destroy_cb (GtkWidget *widget, gpointer data)
> > {
> > CustomerWindow *cw = data;
> >
> > gnc_close_gui_component(cw->component_id);
> >
> > }
> >
> > // This is the CM close handler
> > static void
> > gnc_customer_window_close_handler (gpointer user_data)
> > {
> > CustomerWindow *cw = user_data;
> > GncCustomer *customer = cw_get_customer (cw);
> >
> > gnc_suspend_gui_refresh ();
> >
> > if (cw->dialog_type == NEW_CUSTOMER && customer != NULL) {
> > gncCustomerBeginEdit (customer);
> > gncCustomerDestroy (customer);
> > cw->customer_guid = *xaccGUIDNULL ();
> > }
> >
> > gnc_unregister_gui_component (cw->component_id);
> >
> > gtk_widget_destroy (cw->dialog);
> > cw->dialog = NULL;
> > g_free (cw);
> >
> > gnc_resume_gui_refresh ();
> > }
> >
> > Makes a heck of a lot more sense to me. David?
>
> I think this will work because gtk_widget_destroy correctly handles
> recursive invocation. If the widget is already in the process of being
> destroyed then the call to gtk_widget_destroy from
> gnc_customer_window_close_handler is a noop, otherwise it will actually
> destroy the dialog.
That makes sense since "gtk_widget_destroy" is supposed to mean "break
all your references". If they're already broken, re-calling does
nothing.
I'm not sure if the destroy-signal will get re-delivered in the
recursive case, but I would hope that it wouldn't matter since I would
expect the CM to ignore any events after the un-registration, whether
the events are cached and then discarded because they arrived after
the unregistration, or were discarded immediately because the
component had already been unregistered.
-chris
More information about the gnucash-devel
mailing list