GNOME Bugzilla – Bug 539186
destroy() deletes its Glib::Source instance
Last modified: 2009-05-17 03:11:08 UTC
In the glib C API, g_source_destroy() removes a source from its attached context and marks it as destroyed; that's also the behavior documented for Glib::Source::destroy(). The glibmm implementation, however, ends up deleting the Glib::Source instance, not merely marking it as destroyed. The same instance is later deleted again by its Glib::RefPtr, so calling destroy() can easily and unavoidably cause heap corruption. This issue makes it effectively impossible to safely detach a source from a context in glibmm. I've attached a small example involving a derived source. The same issue is also present for the standard event sources (Glib::TimeoutSource and friends).
Created attachment 113073 [details] glibmm_source_destroy.cc Test case. Observed behavior: " $ ./glibmm_source_destroy > source->destroy() ~DerivedSource() < > source->destroy() (process:19011): GLib-CRITICAL **: g_source_destroy: assertion `source != NULL' failed < *** glibc detected *** ./glibmm_source_destroy: corrupted double-linked list: 0x08ffe4d0 *** ======= Backtrace: ========= /lib/libc.so.6[0xa867e4] /lib/libc.so.6[0xa88613] /lib/libc.so.6(cfree+0x96)[0xa88846] /lib/libglib-2.0.so.0(g_free+0x36)[0xc44356] /usr/lib/libglibmm-2.4.so.1(_ZNK4Glib11MainContext11unreferenceEv+0x1d)[0x729cccd] ./glibmm_source_destroy(_ZN4Glib6RefPtrINS_11MainContextEED1Ev+0x1c)[0x8048e3a] ./glibmm_source_destroy(__gxx_personality_v0+0x23c)[0x8048bb8] /lib/libc.so.6(__libc_start_main+0xe6)[0xa2f5d6] ./glibmm_source_destroy(__gxx_personality_v0+0x55)[0x80489d1] ======= Memory map: ======== 00110000-00111000 r-xp 00110000 00:00 0 [vdso] 0094c000-00959000 r-xp 00000000 fd:00 3999374 /lib/libgcc_s-4.3.0-20080428.so.1 00959000-0095a000 rw-p 0000c000 fd:00 3999374 /lib/libgcc_s-4.3.0-20080428.so.1 009f5000-00a11000 r-xp 00000000 fd:00 3997816 /lib/ld-2.8.so 00a11000-00a12000 r--p 0001c000 fd:00 3997816 /lib/ld-2.8.so 00a12000-00a13000 rw-p 0001d000 fd:00 3997816 /lib/ld-2.8.so 00a19000-00b7c000 r-xp 00000000 fd:00 3997867 /lib/libc-2.8.so 00b7c000-00b7e000 r--p 00163000 fd:00 3997867 /lib/libc-2.8.so 00b7e000-00b7f000 rw-p 00165000 fd:00 3997867 /lib/libc-2.8.so 00b7f000-00b82000 rw-p 00b7f000 00:00 0 00b84000-00bab000 r-xp 00000000 fd:00 3999022 /lib/libm-2.8.so 00bab000-00bac000 r--p 00026000 fd:00 3999022 /lib/libm-2.8.so 00bac000-00bad000 rw-p 00027000 fd:00 3999022 /lib/libm-2.8.so 00baf000-00bb2000 r-xp 00000000 fd:00 3997898 /lib/libdl-2.8.so 00bb2000-00bb3000 r--p 00002000 fd:00 3997898 /lib/libdl-2.8.so 00bb3000-00bb4000 rw-p 00003000 fd:00 3997898 /lib/libdl-2.8.so 00bd1000-00beb000 r-xp 00000000 fd:00 3999377 /lib/libselinux.so.1 00beb000-00bec000 r--p 00019000 fd:00 3999377 /lib/libselinux.so.1 00bec000-00bed000 rw-p 0001a000 fd:00 3999377 /lib/libselinux.so.1 00c05000-00ce5000 r-xp 00000000 fd:00 3999384 /lib/libglib-2.0.so.0.1600.3 00ce5000-00ce6000 rw-p 000e0000 fd:00 3999384 /lib/libglib-2.0.so.0.1600.3 00cf4000-00d33000 r-xp 00000000 fd:00 3999388 /lib/libgobject-2.0.so.0.1600.3 00d33000-00d34000 rw-p 0003f000 fd:00 3999388 /lib/libgobject-2.0.so.0.1600.3 00d65000-00d68000 r-xp 00000000 fd:00 3999389 /lib/libgmodule-2.0.so.0.1600.3 00d68000-00d69000 rw-p 00002000 fd:00 3999389 /lib/libgmodule-2.0.so.0.1600.3 02031000-02036000 r-xp 00000000 fd:00 12044441 /usr/lib/libsigc-2.0.so.0.0.0 02036000-02037000 rw-p 00004000 fd:00 12044441 /usr/lib/libsigc-2.0.so.0.0.0 02ad9000-02bc0000 r-xp 00000000 fd:00 12032670 /usr/lib/libstdc++.so.6.0.10 02bc0000-02bc4000 r--p 000e6000 fd:00 12032670 /usr/lib/libstdc++.so.6.0.10 02bc4000-02bc6000 rw-p 000ea000 fd:00 12032670 /usr/lib/libstdc++.so.6.0.10 02bc6000-02bcb000 rw-p 02bc6000 00:00 0 07269000-072bc000 r-xp 00000000 fd:00 12043870 /usr/lib/libglibmm-2.4.so.1.0.24 072bc000-072be000 rw-p 00053000 fd:00 12043870 /usr/lib/libglibmm-2.4.so.1.0.24 08048000-0804a000 r-xp 00000000 fd:00 17958628 /home/bsilvert/arlut/home/bsilvert/toyprograms/glibmm_source_destroy/glibmm_source_destroy 0804a000-0804b000 rw-p 00001000 fd:00 17958628 /home/bsilvert/arlut/home/bsilvert/toyprograms/glibmm_source_destroy/glibmm_source_destroy 08ffe000-0901f000 rw-p 08ffe000 00:00 0 [heap] b7f00000-b7f21000 rw-p b7f00000 00:00 0 b7f21000-b8000000 ---p b7f21000 00:00 0 b8088000-b808b000 rw-p b8088000 00:00 0 b8098000-b809f000 r--s 00000000 fd:00 12128132 /usr/lib/gconv/gconv-modules.cache b809f000-b80a1000 rw-p b809f000 00:00 0 bfd8c000-bfda1000 rw-p bffeb000 00:00 0 [stack] Aborted "
A destroy function on a ref-counted instance is very odd. I can't see how we could make that make sense for C++ or most other higher-level language bindings. Is there no other way to explicitly "detach" it? I guess there should be.
The g_source_destroy() function is a bit weird, and its name is misleading. It doesn't actually delete the instance per se; it detaches the source from its context and moves it into a "destroyed" state (in which it is an error to call _almost_ all of its methods, but not, eg, g_source_is_destroyed()). The refcount is still responsible for eventually deleting the instance. As far as I'm aware, there's no other way to remove a source from its context, but I'm not sure that there should be---destroy() has, more or less, the semantics you would want in an explicit "detach()" method.
Well, this bug was filed first, but I didn't notice it and there is more discussion on Bug 561885, so I'm going to close this one as a dup. *** This bug has been marked as a duplicate of 561885 ***