GNOME Bugzilla – Bug 127928
Bug related to SigC::Connection::disconnect()
Last modified: 2005-01-28 23:04:25 UTC
There is a bug related to SigC::Connection::disconnect() when changing connections from within a signal handler, more specifically disconnect()ing a slot from a signal and connecting another one. This results in attempts to access data that has been free()'d/deleted when the signal is emitted, leading to random results, from no visible effect at all to crashes.
Output when the test-case is run through valgrind: ==17803== Memcheck, a.k.a. Valgrind, a memory error detector for x86-linux. ==17803== Copyright (C) 2002-2003, and GNU GPL'd, by Julian Seward. ==17803== Using valgrind-2.0.0, a program supervision framework for x86-linux. ==17803== Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward. ==17803== Estimated CPU clock rate is 2842 MHz ==17803== For more details, rerun with: -v ==17803== connected send_cmd: sending 'hello' mainloop: about to emit recv_message signal recv_line: arbitrary reply handle_reply_a: arbitrary reply send_cmd: sending 'user' handle_reply_b: arbitrary reply send_cmd: sending 'pass' handle_reply_c: arbitrary reply mainloop: done emitting recv_message signal ==17803== Invalid read of size 4 ==17803== at 0x40252062: SigC::SignalNode::clear() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x4025200B: SigC::SignalNode::~SignalNode() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x402523AF: SigC::SignalBase::~SignalBase() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x804A1B4: SigC::Signal1<void, std::string, SigC::Marshal<void> >::~Signal1() (in /home/zole/testapp/a.out) ==17803== Address 0x413995D0 is 4 bytes inside a block of size 36 free'd ==17803== at 0x40028DED: __builtin_delete (in /usr/lib/valgrind/vgskin_memcheck.so) ==17803== by 0x40028E18: operator delete(void*) (in /usr/lib/valgrind/vgskin_memcheck.so) ==17803== by 0x40252556: SigC::SignalConnectionNode::~SignalConnectionNode() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x4025215E: SigC::SignalNode::cleanup() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== ==17803== Invalid read of size 4 ==17803== at 0x40252065: SigC::SignalNode::clear() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x4025200B: SigC::SignalNode::~SignalNode() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x402523AF: SigC::SignalBase::~SignalBase() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x804A1B4: SigC::Signal1<void, std::string, SigC::Marshal<void> >::~Signal1() (in /home/zole/testapp/a.out) ==17803== Address 0x413995E8 is 28 bytes inside a block of size 36 free'd ==17803== at 0x40028DED: __builtin_delete (in /usr/lib/valgrind/vgskin_memcheck.so) ==17803== by 0x40028E18: operator delete(void*) (in /usr/lib/valgrind/vgskin_memcheck.so) ==17803== by 0x40252556: SigC::SignalConnectionNode::~SignalConnectionNode() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x4025215E: SigC::SignalNode::cleanup() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== ==17803== Invalid write of size 4 ==17803== at 0x40252068: SigC::SignalNode::clear() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x4025200B: SigC::SignalNode::~SignalNode() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x402523AF: SigC::SignalBase::~SignalBase() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x804A1B4: SigC::Signal1<void, std::string, SigC::Marshal<void> >::~Signal1() (in /home/zole/testapp/a.out) ==17803== Address 0x413995E4 is 24 bytes inside a block of size 36 free'd ==17803== at 0x40028DED: __builtin_delete (in /usr/lib/valgrind/vgskin_memcheck.so) ==17803== by 0x40028E18: operator delete(void*) (in /usr/lib/valgrind/vgskin_memcheck.so) ==17803== by 0x40252556: SigC::SignalConnectionNode::~SignalConnectionNode() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x4025215E: SigC::SignalNode::cleanup() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== ==17803== Invalid write of size 4 ==17803== at 0x40252074: SigC::SignalNode::clear() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x4025200B: SigC::SignalNode::~SignalNode() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x402523AF: SigC::SignalBase::~SignalBase() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x804A1B4: SigC::Signal1<void, std::string, SigC::Marshal<void> >::~Signal1() (in /home/zole/testapp/a.out) ==17803== Address 0x413995D0 is 4 bytes inside a block of size 36 free'd ==17803== at 0x40028DED: __builtin_delete (in /usr/lib/valgrind/vgskin_memcheck.so) ==17803== by 0x40028E18: operator delete(void*) (in /usr/lib/valgrind/vgskin_memcheck.so) ==17803== by 0x40252556: SigC::SignalConnectionNode::~SignalConnectionNode() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== by 0x4025215E: SigC::SignalNode::cleanup() (in /usr/lib/libsigc-1.2.so.5.0.5) ==17803== ==17803== ERROR SUMMARY: 8 errors from 4 contexts (suppressed: 0 from 0) ==17803== malloc/free: in use at exit: 960 bytes in 1 blocks. ==17803== malloc/free: 12 allocs, 11 frees, 1306 bytes allocated. ==17803== For a detailed leak analysis, rerun with: --leak-check=yes ==17803== For counts of detected errors, rerun with: -v
Created attachment 21811 [details] Attaching test-case
I can't reproduce the bug because there is no FreeBSD port of valgrind :( However I had a guess at the bug. Please try the attached patch against lisigc++-1.2 cvs or the libsigc++-1.2.5 tarball and check if the problem is gone.
Created attachment 21942 [details] [review] signal_cleanup_fix.diff
Ok, thanks. I tried your patch but there are still problems, although they have changed slightly: ==9790== Memcheck, a.k.a. Valgrind, a memory error detector for x86-linux. ==9790== Copyright (C) 2002-2003, and GNU GPL'd, by Julian Seward. ==9790== Using valgrind-2.0.0, a program supervision framework for x86-linux. ==9790== Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward. ==9790== Estimated CPU clock rate is 2850 MHz ==9790== For more details, rerun with: -v ==9790== connected send_cmd: sending 'hello' mainloop: about to emit recv_message signal recv_line: arbitrary reply handle_reply_a: arbitrary reply send_cmd: sending 'user' handle_reply_b: arbitrary reply send_cmd: sending 'pass' handle_reply_c: arbitrary reply ==9790== Invalid write of size 4 ==9790== at 0x4024691B: SigC::SignalNode::cleanup() (signal.cc:123) ==9790== by 0x804A463: SigC::SignalNode::exec_unreference() (in /home/zole/testapp/a.out) ==9790== by 0x804A2A4: SigC::SignalExec_::~SignalExec_() (in /home/zole/testapp/a.out) ==9790== by 0x804A1E6: SigC::Signal1<void, std::string, SigC::Marshal<void> >::emit_(std::string const&, void*) (in /home/zole/testapp/a.out) ==9790== Address 0x4139A5E8 is 28 bytes inside a block of size 36 free'd ==9790== at 0x40028DED: __builtin_delete (in /usr/lib/valgrind/vgskin_memcheck.so) ==9790== by 0x40028E18: operator delete(void*) (in /usr/lib/valgrind/vgskin_memcheck.so) ==9790== by 0x40246EA7: SigC::SignalConnectionNode::~SignalConnectionNode() (signal.cc:236) ==9790== by 0x804A4AD: SigC::NodeBase::unreference() (in /home/zole/testapp/a.out) mainloop: done emitting recv_message signal ==9790== ==9790== Invalid read of size 4 ==9790== at 0x40246835: SigC::SignalNode::clear() (signal.cc:51) ==9790== by 0x402467A7: SigC::SignalNode::~SignalNode() (signal.cc:41) ==9790== by 0x804A4AD: SigC::NodeBase::unreference() (in /home/zole/testapp/a.out) ==9790== by 0x40246C88: SigC::SignalBase::~SignalBase() (signal.cc:214) ==9790== Address 0x4139A5E8 is 28 bytes inside a block of size 36 free'd ==9790== at 0x40028DED: __builtin_delete (in /usr/lib/valgrind/vgskin_memcheck.so) ==9790== by 0x40028E18: operator delete(void*) (in /usr/lib/valgrind/vgskin_memcheck.so) ==9790== by 0x40246EA7: SigC::SignalConnectionNode::~SignalConnectionNode() (signal.cc:236) ==9790== by 0x804A4AD: SigC::NodeBase::unreference() (in /home/zole/testapp/a.out) ==9790== ==9790== Invalid write of size 4 ==9790== at 0x4024683E: SigC::SignalNode::clear() (signal.cc:52) ==9790== by 0x402467A7: SigC::SignalNode::~SignalNode() (signal.cc:41) ==9790== by 0x804A4AD: SigC::NodeBase::unreference() (in /home/zole/testapp/a.out) ==9790== by 0x40246C88: SigC::SignalBase::~SignalBase() (signal.cc:214) ==9790== Address 0x4139A5E4 is 24 bytes inside a block of size 36 free'd ==9790== at 0x40028DED: __builtin_delete (in /usr/lib/valgrind/vgskin_memcheck.so) ==9790== by 0x40028E18: operator delete(void*) (in /usr/lib/valgrind/vgskin_memcheck.so) ==9790== by 0x40246EA7: SigC::SignalConnectionNode::~SignalConnectionNode() (signal.cc:236) ==9790== by 0x804A4AD: SigC::NodeBase::unreference() (in /home/zole/testapp/a.out) ==9790== ==9790== Invalid read of size 4 ==9790== at 0x804A48D: SigC::NodeBase::unreference() (in /home/zole/testapp/a.out) ==9790== by 0x4024684F: SigC::SignalNode::clear() (signal.cc:53) ==9790== by 0x402467A7: SigC::SignalNode::~SignalNode() (signal.cc:41) ==9790== by 0x804A4AD: SigC::NodeBase::unreference() (in /home/zole/testapp/a.out) ==9790== Address 0x4139A5D0 is 4 bytes inside a block of size 36 free'd ==9790== at 0x40028DED: __builtin_delete (in /usr/lib/valgrind/vgskin_memcheck.so) ==9790== by 0x40028E18: operator delete(void*) (in /usr/lib/valgrind/vgskin_memcheck.so) ==9790== by 0x40246EA7: SigC::SignalConnectionNode::~SignalConnectionNode() (signal.cc:236) ==9790== by 0x804A4AD: SigC::NodeBase::unreference() (in /home/zole/testapp/a.out) ==9790== ==9790== Invalid read of size 4 ==9790== at 0x804A490: SigC::NodeBase::unreference() (in /home/zole/testapp/a.out) ==9790== by 0x4024684F: SigC::SignalNode::clear() (signal.cc:53) ==9790== by 0x402467A7: SigC::SignalNode::~SignalNode() (signal.cc:41) ==9790== by 0x804A4AD: SigC::NodeBase::unreference() (in /home/zole/testapp/a.out) ==9790== Address 0x4139A5D0 is 4 bytes inside a block of size 36 free'd ==9790== at 0x40028DED: __builtin_delete (in /usr/lib/valgrind/vgskin_memcheck.so) ==9790== by 0x40028E18: operator delete(void*) (in /usr/lib/valgrind/vgskin_memcheck.so) ==9790== by 0x40246EA7: SigC::SignalConnectionNode::~SignalConnectionNode() (signal.cc:236) ==9790== by 0x804A4AD: SigC::NodeBase::unreference() (in /home/zole/testapp/a.out) ==9790== ==9790== ERROR SUMMARY: 7 errors from 5 contexts (suppressed: 0 from 0) ==9790== malloc/free: in use at exit: 960 bytes in 1 blocks. ==9790== malloc/free: 12 allocs, 11 frees, 1306 bytes allocated. ==9790== For a detailed leak analysis, rerun with: --leak-check=yes ==9790== For counts of detected errors, rerun with: -v
Hm, I will try ElectricFence tomorrow. Maybe it also reports some of these errors. It's hard to debug if you don't know where to look ... Do the errors also show up if you omit the recv_line, the handle_reply_a and / or the handle_reply_b slots? I think it would help to further simplify the test case based on this information.
ElectricFence doesn't seem to trigger any errors. I will try valgrind at work. This will have to wait a few days, however, because I'm currently working with a "Knoppix-PC" without hard disk ...
If this happens only in gtkmm rather than a pure libsigc++ program, then you might like to know that I fixed this in glibmm recently. Calling valgrind with --num-callers=20 often gives more context.
Created attachment 30462 [details] [review] Patch to fix bug 127928 in libsigc++ 1.2.5. Try this patch... it fixes the test case completely on my system.
Created attachment 30468 [details] [review] Better patch for 1.2.5 This one is even better.
Martin, does this look OK?
I don't really know the background of the code in the affected routine. I remember that there already were patches from different people to this. So me too, I can only guess that the patch is okay if all test cases are still working...
I would prefer to see a version of this patch that did not include irrelevant changes, such as additions of whitespace and consts, but Martin might not care about that as much as me. If so, this should probably be committed if the tests cases still work with it.
I have applied this patch. The change seems simple and good.
Created attachment 36674 [details] [review] libsigc_1p2_remove.patch