[gtkmm] Possible bug in SigC::Connection::disconnect()
- From: Ole André Vadla Ravnĺs <ole ravnas lyse net>
- To: gtkmm-list gnome org
- Subject: [gtkmm] Possible bug in SigC::Connection::disconnect()
- Date: Sun, 23 Nov 2003 23:59:52 +0100
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;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]