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 145571 - sigc::connection::disconnect() causes crash
sigc::connection::disconnect() causes crash
Status: RESOLVED FIXED
Product: gtkmm
Classification: Bindings
Component: general
2.4
Other Linux
: Normal normal
: ---
Assigned To: gtkmm-forge
gtkmm-forge
Depends on:
Blocks:
 
 
Reported: 2004-07-07 13:55 UTC by Ole Laursen
Modified: 2004-12-22 21:47 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Test case that crashes (950 bytes, text/plain)
2004-07-07 13:56 UTC, Ole Laursen
Details
test_simpler.cc (797 bytes, text/x-c++src)
2004-07-09 12:41 UTC, Murray Cumming
Details

Description Ole Laursen 2004-07-07 13:55:50 UTC
I've recently ported an application to gtkmm 2.4 from gtkmm 2.2 and have started
experiencing crashes in the preferences window in the code that let users choose
keyboard keys. The idea in that code is to use Gtk::Buttons to represent keys -
when a button is pressed, the focus is grabbed until a new key is pressed which
then replaces the contents of the button.

More specifically, I connect a handler to the clicked signal of a button. That
handler clears the text of the button, adds a modal grab and installs a callback
on the signal_key_press_event(), saving the sigc::connection. The callback then
removes the modal grab, calls the disconnect() method on the saved connection
and puts a textual representation of the pressed key inside the button (so it is
a one-shot callback).

The problem is that the above has stopped working in gtkmm 2.4 - instead it
seems to cause memory corruption. The attached test program shows this. I had to
 allocate the button dynamically for the error to show up. Compile it with

  g++ base.cc -o base -g -Wall `pkg-config --libs --cflags gtkmm-2.4`

run it with ./base and it crashes horribly. This is with gtkmm-2.4.4 and
sigc++-2.0.3 on Debian unstable. I have no idea where the problem is. The
backtrace is pretty boring:

(gdb) run
Starting program: /home/ole/tmp/base
Button clicked
Key event cb

Program received signal SIGSEGV, Segmentation fault.
0x40666bd3 in sigc::slot_base::~slot_base () from /usr/lib/libsigc-2.0.so.0
(gdb) bt
  • #0 sigc::slot_base::~slot_base
    from /usr/lib/libsigc-2.0.so.0
  • #1 Glib::SignalProxyConnectionNode::destroy_notify_handler
    from /usr/lib/libglibmm-2.4.so.1
  • #2 g_signal_type_cclosure_new
    from /usr/lib/libgobject-2.0.so.0
  • #3 ??
  • #4 ??
  • #5 ??
  • #6 ??
  • #7 ??
  • #8 ??
  • #9 g_closure_unref
    from /usr/lib/libgobject-2.0.so.0

Comment 1 Ole Laursen 2004-07-07 13:56:54 UTC
Created attachment 29319 [details]
Test case that crashes
Comment 2 Murray Cumming 2004-07-08 15:50:29 UTC
I can't reproduce the crash on debian testing, either with my built-from-source
gtkmm, or with the libsigc++ 2.0.3 and gtkmm 2.4.2 debian packages that are in
testing.

I have tried clicking on the button and pressing keys. I guess it crashes for
you whe you press a key. Valgrind also did not show anything interesting.

Did you build libsigc++, glibmm, and gtkmm from source, or are you using the
debian packages.

If you built them from source, did you rebuild glibmm and gtkmm after you
updated libsigc++? (an earlier version of libsigc++ 2.0.x was very broken) 

Or, can you tell us more about your architecture? Is this a regular x86 PC?
Comment 3 Ole Laursen 2004-07-08 17:52:55 UTC
I'm using the Debian unstable packages on a Pentium III. The crash occurs if you
start the program and press enter a couple of times (say four or five).
Comment 4 Ole Laursen 2004-07-09 11:26:53 UTC
I didn't think of running it inside Valgrind. Good idea. Now it does
not actually crash, but instead I get this when I hit enter twice:

button_clicked
key_event_cb
==2884==
==2884== Invalid read of size 4
==2884==    at 0x3C65FD6A:
Glib::SignalProxyConnectionNode::destroy_notify_handler(void*, _GClosure*) (in
/usr/lib/libglibmm-2.4.so.1.0.3)
==2884==    by 0x3C779274: (within /usr/lib/libgobject-2.0.so.0.400.2)
==2884==    by 0x3C77868D: g_closure_unref (in /usr/lib/libgobject-2.0.so.0.400.2)
==2884==    by 0x3C78E50C: (within /usr/lib/libgobject-2.0.so.0.400.2)
==2884==  Address 0x3D037A30 is 12 bytes inside a block of size 16 free'd
==2884==    at 0x3C01FA3C: operator delete(void*) (vg_replace_malloc.c:129)
==2884==    by 0x3C65FD34: Glib::SignalProxyConnectionNode::notify(void*) (in
/usr/lib/libglibmm-2.4.so.1.0.3)
==2884==    by 0x3C67C9E7: sigc::internal::slot_rep::disconnect() (in
/usr/lib/libsigc-2.0.so.0.0.0)
==2884==    by 0x3C67CDFB: sigc::slot_base::disconnect() (in
/usr/lib/libsigc-2.0.so.0.0.0)
Comment 5 Murray Cumming 2004-07-09 12:22:59 UTC
> The crash occurs if you start the program and press enter a couple of times
(say four or five)

Now, I see what you mean.

Strangely, it crashes for me in my built-from-source environment, but not when
I'm using the debian packages (all unstable + the gtkmm package from testing). 
Comment 6 Murray Cumming 2004-07-09 12:41:56 UTC
Created attachment 29377 [details]
test_simpler.cc

Here (test_simpler.cc) is a simpler test case. Even if it doesn't crash, it
shows the error in valgrind, and that's what we need to deal with.
Comment 7 Murray Cumming 2004-07-09 15:12:45 UTC
The valgrind output:

==29323==
==29323== Invalid read of size 4
==29323==    at 0x3C643D9A:
Glib::SignalProxyConnectionNode::destroy_notify_handler(void*, _GClosure*)
(signalproxy_connectionnode.cc:73)
==29323==    by 0x3C75B984: closure_invoke_notifiers (gclosure.c:109)
==29323==    by 0x3C75AD9D: g_closure_unref (gclosure.c:347)
==29323==    by 0x3C770C1C: handler_unref_R (gsignal.c:590)
==29323==    by 0x3C76EFF4: signal_emit_unlocked_R (gsignal.c:2567)
==29323==    by 0x3C76E326: g_signal_emit_valist (gsignal.c:2195)
==29323==    by 0x3C76E623: g_signal_emit (gsignal.c:2239)
==29323==    by 0x3C3818B4: gtk_button_clicked (gtkbutton.c:719)
==29323==    by 0x3C3828CA: gtk_real_button_released (gtkbutton.c:1220)
==29323==    by 0x3C14F358: Gtk::Button_Class::released_callback(_GtkButton*)
(button.cc:219)
==29323==    by 0x3C76F860: g_cclosure_marshal_VOID__VOID (gmarshal.c:77)
==29323==    by 0x3C75B6C6: g_type_class_meta_marshal (gclosure.c:514)
==29323==    by 0x3C75B32F: g_closure_invoke (gclosure.c:437)
==29323==    by 0x3C76EB8D: signal_emit_unlocked_R (gsignal.c:2366)
==29323==    by 0x3C76E326: g_signal_emit_valist (gsignal.c:2195)
==29323==    by 0x3C76E623: g_signal_emit (gsignal.c:2239)
==29323==    by 0x3C381804: gtk_button_released (gtkbutton.c:711)
==29323==    by 0x3C38274A: gtk_button_button_release (gtkbutton.c:1136)
==29323==    by 0x3C1F5371:
Gtk::Widget_Class::button_release_event_callback(_GtkWidget*, _GdkEventButton*)
(widget.cc:3798)
==29323==    by 0x3C43D603: _gtk_marshal_BOOLEAN__BOXED (gtkmarshalers.c:82)
==29323==  Address 0x3CFC8D70 is 12 bytes inside a block of size 16 free'd
==29323==    at 0x3C01FA3C: operator delete(void*) (vg_replace_malloc.c:129)
==29323==    by 0x3C643D64: Glib::SignalProxyConnectionNode::notify(void*)
(signalproxy_connectionnode.cc:60)
==29323==    by 0x3C661A77: sigc::internal::slot_rep::disconnect() (slot_base.cc:37)
==29323==    by 0x3C661E8B: sigc::slot_base::disconnect() (slot_base.cc:142)
==29323==    by 0x3C6619AB: sigc::connection::disconnect() (connection.cc:83)
==29323==    by 0x804DDE6: Test::button_clicked() (in /home/murrayc/a.out)
==29323==    by 0x804E3C8: sigc::bound_mem_functor0<void, Test>::operator()()
const (in /home/murrayc/a.out)
==29323==    by 0x804E253: sigc::adaptor_functor<sigc::bound_mem_functor0<void,
Test> >::operator()() const (in /home/murrayc/a.out)
==29323==    by 0x804E23D:
sigc::internal::slot_call0<sigc::bound_mem_functor0<void, Test>,
void>::call_it(sigc::internal::slot_rep*) (in /home/murrayc/a.out)
==29323==    by 0x3C643BDC:
Glib::SignalProxyNormal::slot0_void_callback(_GObject*, void*) (slot.h:426)
==29323==    by 0x3C76F860: g_cclosure_marshal_VOID__VOID (gmarshal.c:77)
==29323==    by 0x3C75B32F: g_closure_invoke (gclosure.c:437)
==29323==    by 0x3C76F1E4: signal_emit_unlocked_R (gsignal.c:2506)
==29323==    by 0x3C76E326: g_signal_emit_valist (gsignal.c:2195)
==29323==    by 0x3C76E623: g_signal_emit (gsignal.c:2239)
==29323==    by 0x3C3818B4: gtk_button_clicked (gtkbutton.c:719)
==29323==    by 0x3C3828CA: gtk_real_button_released (gtkbutton.c:1220)
==29323==    by 0x3C14F358: Gtk::Button_Class::released_callback(_GtkButton*)
(button.cc:219)
==29323==    by 0x3C76F860: g_cclosure_marshal_VOID__VOID (gmarshal.c:77)
==29323==    by 0x3C75B6C6: g_type_class_meta_marshal (gclosure.c:514)


Comment 8 Murray Cumming 2004-07-09 21:12:07 UTC
This might be caused by the fact that destroy_notify callbacks are not called
during GTK+ signal disconnection if the callback is running - destroy_notify
callbacks are then called after the callback has returned.

I'm working on a patch.
Comment 9 Murray Cumming 2004-07-10 06:36:32 UTC
I think I have fixed this in cvs - now we always let the ConnectionNode be
deleted in destroy_notify, because that is always called. I can't find any leaks
caused by this.

Thanks a lot for the test case.