After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 315874 - Container::signal_remove handler not called sometimes.
Container::signal_remove handler not called sometimes.
Status: RESOLVED FIXED
Product: gtkmm
Classification: Bindings
Component: general
unspecified
Other Linux
: Normal major
: ---
Assigned To: gtkmm-forge
gtkmm-forge
Depends on:
Blocks:
 
 
Reported: 2005-09-09 23:36 UTC by Philip Langdale
Modified: 2013-02-27 16:11 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Test case (561 bytes, text/x-c++src)
2005-09-09 23:56 UTC, Philip Langdale
  Details
remove.patch (7.69 KB, patch)
2005-12-20 14:05 UTC, Murray Cumming
none Details | Review

Description Philip Langdale 2005-09-09 23:36:24 UTC
Compile and run the attached test case. (It is a modified child_widget2 testcase).

This bug emerged in testing view::VisibilityBox which attaches add/remove
handlers to all containers inside it (to a first approximation).

If a child of one of those containers is deleted before it is removed, then gtk+
emits the "remove" signal as usual but the c++ handler is still attached because
trackable's destructor hasn't been reached yet. However, the child's wrapper
reports itself as deleted so the signal proxy tries to recreate it but this is
refused because the gtk+ object is being destroyed, causing a warning to be
shown and the signal not to be emitted.

In contrast, a C handler will be notified as normal.

So, it would seem that the wrapper must be changed to consider itself existing
until gtk_widget_dispose returns at the very least; it's perfectly valid to
listen for the remove signal and to be notified at delete time. I'm not sure
what the implications of this lifetime extension would be.

I've filed the bug under glibmm because I consider this a bug in the base
wrapping code rather than in how gtkcontainer is specifically wrapped.
Comment 1 Philip Langdale 2005-09-09 23:56:31 UTC
Created attachment 52040 [details]
Test case
Comment 2 Murray Cumming 2005-11-24 08:45:19 UTC
Sorry for the lack of response. I hope I have time to investigate in January.
Comment 3 Murray Cumming 2005-12-02 14:19:35 UTC
Confirmed. When closing the window, I get:

(a.out:29961): glibmm-WARNING **: Glib::create_new_wrapper: Attempted to create
a 2nd C++ wrapper for a C instance whose C++ wrapper has been deleted.

(a.out:29961): glibmm-WARNING **: failed to wrap type of 'gtkmm__GtkVBox'
Child removed

Comment 4 Murray Cumming 2005-12-02 14:29:47 UTC
The backtrace with --g-fatal-warnings:

  • #0 IA__g_logv
    at gmessages.c line 503
  • #1 IA__g_log
    at gmessages.c line 517
  • #2 create_new_wrapper
    at wrap.cc line 56
  • #3 Glib::wrap_auto
    at wrap.cc line 138
  • #4 Glib::wrap
    at widget.cc line 2832
  • #5 (anonymous namespace)::Container_signal_remove_callback
    at container.cc line 210
  • #6 IA__g_cclosure_marshal_VOID__OBJECT
    at gmarshal.c line 636
  • #7 IA__g_closure_invoke
    at gclosure.c line 490
  • #8 signal_emit_unlocked_R
    at gsignal.c line 2519
  • #9 IA__g_signal_emit_valist
    at gsignal.c line 2208
  • #10 IA__g_signal_emit
    at gsignal.c line 2252
  • #11 IA__gtk_container_remove
    at gtkcontainer.c line 995
  • #12 gtk_widget_dispose
    at gtkwidget.c line 6648
  • #13 Gtk::Widget_Class::dispose_vfunc_callback
    at widget.cc line 508
  • #14 IA__g_object_run_dispose
    at gobject.c line 569
  • #15 IA__gtk_object_destroy
    at gtkobject.c line 363
  • #16 Gtk::Object::_destroy_c_instance
    at object.cc line 166
  • #17 Gtk::Object::destroy_
    at object.cc line 264
  • #18 ~VBox
    at box.cc line 461
  • #19 MyWindow::~MyWindow
  • #20 main

Comment 5 Murray Cumming 2005-12-02 14:41:14 UTC
Here's one of my (usually wrong) ideas:
Maybe Container_signal_remove_callback() (the C callbacks that call the
connected handler slots when a signal is emitted) should do the same clever
things that Container_Class::remove_callback_custom() (The default signal
handler) does. I guess that the signal handlers are called before the default
signal handler, and this cleverness should happen as soon as possible. This
could stop the warning, at least, though I don't think the handler would be called.
Comment 6 Murray Cumming 2005-12-02 14:57:31 UTC
And I guess that you connected to the signal because you noticed that an
on_remove() override was being not called.

> it's perfectly valid to listen for the remove signal and to be notified at
delete time

If possible, I'd like to make that work, though preventing crashes would be a
priority if I have to choose.
Comment 7 Murray Cumming 2005-12-20 14:05:05 UTC
Created attachment 56204 [details] [review]
remove.patch

This patch should fix the warning. I haven't committed it yet because the test case is currently segfaulting on close even without the patch. Investigating.
Comment 8 Murray Cumming 2005-12-23 15:31:20 UTC
Using vmware (woot!), I used Ubuntu Breezy to check that this extra crash was just a problem with glib/GTK+ HEAD. I have applied this patch to both branches, which fixes the warning/crash. But the problem remains that the "remove" signal handler won't be called sometimes, as shown by the test case.
Comment 9 Philip Langdale 2005-12-24 06:29:14 UTC
Thanks for looking in to this Murray.

The reason why we didn't try using an on_remove override is that the specific widget in question (the ContentBox) recursively listens for remove events on all containers under it in the hierarchy - obviously, we can't override methods on those objects; so as you observe, we still have a problem (at least we have a workaround in using the underlying gsignal).
Comment 10 Kjell Ahlstedt 2012-12-12 19:08:44 UTC
I think this bug is closely related to gtkmm bug 605728.
When I apply the patch in bug 605728, comment 2, MyWindow::OnChildRemoved()
is called when the window is closed.

The following backtrace shows how OnChildRemoved() is called.

  • #0 MyWindow::OnChildRemoved
    at main.cc line 30
  • #1 sigc::bound_mem_functor1<void, MyWindow, Gtk::Widget*>::operator()
    at /opt/gnome/include/sigc++-2.0/sigc++/functors/mem_fun.h line 1851
  • #2 sigc::adaptor_functor<sigc::bound_mem_functor1<void, MyWindow, Gtk::Widget*> >::operator()<Gtk::Widget* const&>
    at /opt/gnome/include/sigc++-2.0/sigc++/adaptors/adaptor_trait.h line 84
  • #3 sigc::internal::slot_call1<sigc::bound_mem_functor1<void, MyWindow, Gtk::Widget*>, void, Gtk::Widget*>::call_it
    at /opt/gnome/include/sigc++-2.0/sigc++/functors/slot.h line 137
  • #4 operator()
    at /opt/gnome/include/sigc++-2.0/sigc++/functors/slot.h line 515
  • #5 operator()
    at container.cc line 76
  • #6 Container_signal_remove_callback_normal
    at container.cc line 67
  • #8 g_cclosure_marshal_VOID__OBJECT
    at gmarshal.c line 1272
  • #9 g_closure_invoke
    at gclosure.c line 777
  • #10 signal_emit_unlocked_R
    at gsignal.c line 3637
  • #11 g_signal_emit_valist
    at gsignal.c line 3315
  • #12 g_signal_emit
    at gsignal.c line 3371
  • #13 gtk_container_remove
    at gtkcontainer.c line 1547
  • #14 gtk_widget_dispose
    at gtkwidget.c line 10298
  • #15 Gtk::Widget_Class::dispose_vfunc_callback
    at widget.cc line 598
  • #16 g_object_run_dispose
    at gobject.c line 1062
  • #17 Gtk::Object::_release_c_instance
    at object.cc line 145
  • #18 Gtk::Object::destroy_
    at object.cc line 251
  • #19 Gtk::VBox::~VBox
    at hvbox.cc line 115
  • #20 MyWindow::~MyWindow
    at main.cc line 3
  • #21 main
    at main.cc line 40

When the patch has been applied, Gtk::Object::_release_c_instance() calls
disconnect_cpp_wrapper() _after_ it calls g_object_run_dispose().
Container_signal_remove_callback() finds that gtkmm_child_already_deleted is
false. It calls Container_signal_remove_callback_normal() which calls
OnChildRemoved().

This backtrace is slightly different from the one in bug 605728, comment 1.
That backtrace shows the call of an overridden default signal handler.

This kind of call of a 'remove' signal handler is not always safe.
MyWindow::OnChildRemoved() is called while MyWindow and MyWindow::vbox is
being deleted. If MyWindow had contained member data declared after vbox,
and OnChildRemoved() had accessed that data, then it had accessed deleted data.

I have not yet pushed the patch in bug 605728, comment 2. I hope that someone
with very good knowledge of gtkmm will have time to comment on it. I have not
found any problem with it, apart from the just mentioned risk with some
'remove' signal handlers, a risk which I would say is acceptable.
Comment 11 Kjell Ahlstedt 2013-02-27 16:11:07 UTC
I've now pushed the patch in bug 605728. It also fixes this bug.

I've also moved this bug from glibmm to gtkmm. It only affects the removal of
Gtk::Widgets, and the fix is a modification in gtkmm.