Re: [gtkmm] Possible bug in SigC::Connection::disconnect()



I've investigated this issue a little further now, and I think I see
what's wrong. I'm not sure if the way I'm using the libsigc++ library is
correct. What I do, basically, is connect a slot to a signal. When this
signal is emitted, the slot is called, and from there I disconnect the
current slot [from the signal] and connect another one. Now, I suspect
this might no be legal? Maybe it should be mentioned in the
documentation if that's the case? Any ideas anyone?

Ole André


On Sun, 2003-11-23 at 23:59, Ole André Vadla Ravnĺs wrote:
> I think I've encountered a possible bug with the disconnect() method of
> SigC::Connection (after several days of headscratching :-) ) To me it
> seems like disconnect() doesn't clean up properly, and causes future
> emit()'s on the given signal to make valgrind spew out memory-errors --
> at best, or, worse, which happened in my case under some circumstances,
> results in a crash (segfault).
> 
> Below is the output from valgrind on the test-app involved. No errors
> are issued when NO_WEIRD_BEHAVIOUR is defined (removing the disconnect()
> call).
> 
> At the bottom is sourcecode for the test-app.
> 
> Ole André
> 
> 
> ==669== Memcheck, a.k.a. Valgrind, a memory error detector for
> x86-linux.
> ==669== Copyright (C) 2002-2003, and GNU GPL'd, by Julian Seward.
> ==669== Using valgrind-2.0.0, a program supervision framework for
> x86-linux.
> ==669== Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward.
> ==669== Estimated CPU clock rate is 2853 MHz
> ==669== For more details, rerun with: -v
> ==669== 
> connected
> send_cmd: sending 'hello'
> recv_line: odd reply
> handle_reply_a: odd reply
> send_cmd: sending 'user'
> handle_reply_b: odd reply
> send_cmd: sending 'pass'
> handle_reply_c: odd reply
> recv_line: odd reply
> ==669== Invalid read of size 1
> ==669==    at 0x804A558: SigC::ConnectionNode::blocked() const (in
> /home/zole/testapp/a.out)
> ==669==    by 0x8049DC7: SigC::Signal1<void, std::string,
> SigC::Marshal<void> >::emit(std::string const&) (in
> /home/zole/testapp/a.out)
> ==669==    by 0x80499EA: client::recv_idler() (in
> /home/zole/testapp/a.out)
> ==669==    by 0x804A2BF: SigC::ObjectSlot0_<bool, client>::proxy(void*)
> (in /home/zole/testapp/a.out)
> ==669==    Address 0x415756A4 is 8 bytes inside a block of size 36
> free'd
> ==669==    at 0x40028DED: __builtin_delete (in
> /usr/lib/valgrind/vgskin_memcheck.so)
> ==669==    by 0x40028E18: operator delete(void*) (in
> /usr/lib/valgrind/vgskin_memcheck.so)
> ==669==    by 0x402C7556:
> SigC::SignalConnectionNode::~SignalConnectionNode() (in
> /usr/lib/libsigc-1.2.so.5.0.5)
> ==669==    by 0x402C715E: SigC::SignalNode::cleanup() (in
> /usr/lib/libsigc-1.2.so.5.0.5)
> ==669== 
> ==669== Invalid read of size 4
> ==669==    at 0x804A3FE: SigC::Signal1<void, std::string,
> SigC::Marshal<void> >::emit_(std::string const&, void*) (in
> /home/zole/testapp/a.out)
> ==669==    by 0x8049DC7: SigC::Signal1<void, std::string,
> SigC::Marshal<void> >::emit(std::string const&) (in
> /home/zole/testapp/a.out)
> ==669==    by 0x80499EA: client::recv_idler() (in
> /home/zole/testapp/a.out)
> ==669==    by 0x804A2BF: SigC::ObjectSlot0_<bool, client>::proxy(void*)
> (in /home/zole/testapp/a.out)
> ==669==    Address 0x415756B8 is 28 bytes inside a block of size 36
> free'd
> ==669==    at 0x40028DED: __builtin_delete (in
> /usr/lib/valgrind/vgskin_memcheck.so)
> ==669==    by 0x40028E18: operator delete(void*) (in
> /usr/lib/valgrind/vgskin_memcheck.so)
> ==669==    by 0x402C7556:
> SigC::SignalConnectionNode::~SignalConnectionNode() (in
> /usr/lib/libsigc-1.2.so.5.0.5)
> ==669==    by 0x402C715E: SigC::SignalNode::cleanup() (in
> /usr/lib/libsigc-1.2.so.5.0.5)
> handle_reply_c: odd reply
> recv_line: odd reply
> (...)
> 
> 
> /*
>  * "Simple" test-case to trigger a possible
> SigC::Connection::disconnect() bug
>  *
>  * Compile with:
>  *   g++ $(pkg-config --cflags --libs glibmm-2.0) -Wall
> disconnect_bug.cpp -o disconnect_bug
>  *
>  * Run through valgrind to see the errors reported (which,
> unfortunately,
>  * doesn't make this simple app crash).
>  *
>  * Compile with DONT_WANT_WEIRD_BEHAVIOUR defined, run through valgrind
> once
>  * again and just watch the errors disappear.
>  */
> 
> #include <iostream>
> #include <string>
> #include <sigc++/sigc++.h>
> #include <glibmm.h>
> 
> using std::cout;
> using std::endl;
> using std::string;
> 
> class client : public SigC::Object {
> public:
> 	client() {}
> 	~client() {}
> 	
> 	void connect();
> 	
> 	SigC::Signal1<void, string> recv_message;
> private:
> 	SigC::Connection handler_conn;
> 
> 	void send_cmd(string c, SigC::Slot1<void, string> handler);
> 	
> 	void handle_reply_a(string r);
> 	void handle_reply_b(string r);
> 	void handle_reply_c(string r);
> 
> 	bool recv_idler();
> };
> 
> void client::connect()
> {
> 	cout << "connected" << endl;
> 
> 	Glib::signal_idle().connect(SigC::slot(*this, &client::recv_idler));
> 
> 	send_cmd("hello", SigC::slot(*this, &client::handle_reply_a));
> }
> 
> void client::send_cmd(string c, SigC::Slot1<void, string> handler)
> {
> 	cout << "send_cmd: sending '" << c << "'" << endl;
> 
> #ifndef NO_WEIRD_BEHAVIOUR
> 	if (handler_conn.connected())
> 		handler_conn.disconnect();
> #endif
> 	
> 	handler_conn = recv_message.connect(handler);
> }
> 
> void client::handle_reply_a(string r)
> {
> 	cout << "handle_reply_a: " << r << endl;
> 
> 	send_cmd("user", SigC::slot(*this, &client::handle_reply_b));
> }
> 
> void client::handle_reply_b(string r)
> {
> 	cout << "handle_reply_b: " << r << endl;
> 	
> 	send_cmd("pass", SigC::slot(*this, &client::handle_reply_c));
> }
> 
> void client::handle_reply_c(string r)
> {
> 	cout << "handle_reply_c: " << r << endl;
> }
> 
> bool client::recv_idler()
> {
> 	sleep(1);
> 	
> 	recv_message.emit("odd reply");
> 
> 	return true;
> }
> 
> void recv_line(string s)
> {
> 	cout << "recv_line: " << s << endl;
> }
> 
> int main(int argc, char *argv[])
> {
> 	client c;
> 	Glib::RefPtr<Glib::MainLoop> loop = Glib::MainLoop::create();
> 
> 	c.recv_message.connect(SigC::slot(recv_line));
> 
> 	c.connect();
> 
> 	loop->run();
> 
> 	return 0;
> }
> 
> 
> _______________________________________________
> gtkmm-list mailing list
> gtkmm-list gnome org
> http://mail.gnome.org/mailman/listinfo/gtkmm-list
> 




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]