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 561884 - Glibmm::Source - wrong impl. of [un]reference - dating Jan 2006?
Glibmm::Source - wrong impl. of [un]reference - dating Jan 2006?
Status: RESOLVED OBSOLETE
Product: glibmm
Classification: Bindings
Component: io
2.18.x
Other All
: Normal critical
: ---
Assigned To: gtkmm-forge
gtkmm-forge
Depends on:
Blocks:
 
 
Reported: 2008-11-22 01:31 UTC by Cristi Posoiu
Modified: 2009-01-03 11:33 UTC
See Also:
GNOME target: ---
GNOME version: 2.23/2.24



Description Cristi Posoiu 2008-11-22 01:31:23 UTC
Please describe the problem:
I need to start a timer (Glib::TimeoutSource) but be able to stop it before it necessarily signals. So I have to call destroy() (just unrefering my timer pointer won't stop the timer).
On the other hand, I'm reusing the same Glib::RefPtr variable. And I'll get 
GLib-CRITICAL **: g_source_unref: assertion `source != NULL' failed

Seems to be the same thing discussed even here (Jan 2006) ? :
http://markmail.org/message/7shyxixmeevv7ojw#query:glibmm timeoutsource still+page:1+mid:smh2eorgiblrpqrz+state:results

Looking at code, it seems the problem might be the bogus implementation of GLib::Source::[un]reference(): they blindly say to unreference gobject_ while, since a destroy might have been called, the  variable gets to be 0 (from Source's destructor). And the unreference function is called by destructor/swap inside Glib::RefPtr.


Steps to reproduce:
Code, not showing my exact problem... but, still: (see comment on how to compile):

#include <glibmm.h>

// g++ -g `pkg-config --cflags glibmm-2.4` `pkg-config --libs glibmm-2.4`  t.cpp


static bool on_t1(Glib::RefPtr<Glib::MainLoop> l)
{
	printf("timer 1\n");
	l->quit();
	return FALSE;
}


int main(int argc, char *argv[])
{
	Glib::init();

	Glib::RefPtr<Glib::MainLoop> loop(Glib::MainLoop::create());

	Glib::RefPtr<Glib::TimeoutSource> t1;

	t1 = Glib::TimeoutSource::create(1000);
	t1->connect(sigc::bind(sigc::ptr_fun(on_t1), loop));
	t1->attach();
	
	loop->run();
	printf("ending loop (timer 1=%p)\n", t1->gobj());
	t1.clear();
	return 0;
}


Actual results:
Get an assertion failure:
GLib-CRITICAL **: g_source_unref: assertion `source != NULL' failed

Expected results:
to not have the assertion failure :)

Does this happen every time?
yes

Other information:
Patch is simple: modify Glib::[un]reference to do ref/unref only if gobject_ is not 0/NULL. Well, I guess gobj_copy() as well. But most critical is unreference()

Last minute update: ay.. there seem to be bigger problems in there, w/ C GSource mistunderstanding and destroy, and memory access. Will post another bug :-( (which will probably make "obsolete" this bug.
Comment 1 Murray Cumming 2009-01-03 00:25:49 UTC
So should this bug be closed, while keeping the other one open?
Comment 2 Cristi Posoiu 2009-01-03 11:32:52 UTC
Wider bug that covers this one is 561885 - http://bugzilla.gnome.org/show_bug.cgi?id=561885

Notes:
- wondering why GSource (in C lib) isn't derived from GObject?
- wondering how you're going to reimplement C++ GSource constructor and destructor so that you wrap with the same C++ object the same C GSource object.
  If that can't be done [easily], then, since Glib::RefPtr comparison won't work anymore, make the Glib::RefPtr compare the pCppObject_->gobj() values?

Will mark it as OBSOLETE  - feel free to put it in another state (Duplicate?)