Ticket #10721: deadlock-boost-signals2.cpp

File deadlock-boost-signals2.cpp, 1.7 KB (added by Stefan Bühler <buehler@…>, 8 years ago)
Line 
1
2/*
3compile with:
4
5 g++ -o deadlock-boost-signals2 deadlock-boost-signals2.cpp -lboost_signals -pthread
6
7run with gdb or valgrind:
8
9 valgrind --tool=helgrind ./deadlock-boost-signals2
10*/
11
12#include <assert.h>
13#include <boost/shared_ptr.hpp>
14#include <boost/make_shared.hpp>
15#include <boost/signals2/signal.hpp>
16
17typedef boost::signals2::signal<void()> Signal;
18
19class SelfReference: private boost::noncopyable
20{
21public:
22 boost::shared_ptr<SelfReference> m_self;
23 boost::shared_ptr<Signal> m_signal;
24
25 boost::signals2::connection m_conReleaseSelf;
26 boost::signals2::connection m_conDoNothing;
27
28 SelfReference()
29 {
30 m_signal = boost::make_shared<Signal>();
31 }
32
33 ~SelfReference()
34 {
35 // the first slot (ReleaseSelf) has been called; now the trackable object (this)
36 // was released, while the second slot is locked
37 assert(!m_conReleaseSelf.connected());
38 // the second slot is locked, and we enter a recursive (pthread: dead) lock
39 assert(m_conDoNothing.connected());
40 m_conReleaseSelf.disconnect();
41 m_conDoNothing.disconnect();
42 // enter recursive (pthread: dead) lock again:
43 assert(m_signal->empty());
44 }
45
46 void ReleaseSelf()
47 {
48 m_self.reset();
49 }
50
51 static void DoNothing()
52 {
53 }
54
55 static void Run()
56 {
57 boost::shared_ptr<Signal> signal;
58 {
59 boost::shared_ptr<SelfReference> obj = boost::make_shared<SelfReference>();
60 obj->m_self = obj;
61 signal = obj->m_signal;
62
63 obj->m_conReleaseSelf = signal->connect(Signal::slot_type(&SelfReference::ReleaseSelf, obj.get()).track(obj));
64 obj->m_conDoNothing = signal->connect(Signal::slot_type(&SelfReference::DoNothing));
65 }
66 (*signal)();
67 }
68};
69
70int main() {
71 SelfReference::Run();
72
73 return 0;
74}