diff options
author | Andreas Volz <andreas@er00923n.fritz.box> | 2011-11-28 08:23:32 +0100 |
---|---|---|
committer | Andreas Volz <andreas@er00923n.fritz.box> | 2011-11-28 08:23:32 +0100 |
commit | 82c63b289d359bf1b2255ba4e721e69118d26fb4 (patch) | |
tree | 8c1490cacb3236cf7ad2f2126a41850886e74186 | |
parent | d1ec2544d52df89daa0415a755271a8c0e4b35e7 (diff) | |
download | dbus-c++-82c63b289d359bf1b2255ba4e721e69118d26fb4.tar.gz |
sf.net ticket 2905915 - Fix dbus signal handler deadlock
From: sf.net user 'nabertech'
-rw-r--r-- | include/dbus-c++/dispatcher.h | 3 | ||||
-rw-r--r-- | src/dispatcher.cpp | 56 |
2 files changed, 50 insertions, 9 deletions
diff --git a/include/dbus-c++/dispatcher.h b/include/dbus-c++/dispatcher.h index 728f9d8..48c2ed3 100644 --- a/include/dbus-c++/dispatcher.h +++ b/include/dbus-c++/dispatcher.h @@ -174,8 +174,11 @@ public: struct Private; private: + void dispatch_pending(Connection::PrivatePList& pending_queue); DefaultMutex _mutex_p; + DefaultMutex _mutex_p_copy; + Connection::PrivatePList _pending_queue; }; diff --git a/src/dispatcher.cpp b/src/dispatcher.cpp index 57c584a..cea3d23 100644 --- a/src/dispatcher.cpp +++ b/src/dispatcher.cpp @@ -181,29 +181,67 @@ bool Dispatcher::has_something_to_dispatch() void Dispatcher::dispatch_pending() { - _mutex_p.lock(); + while (1) + { + _mutex_p.lock(); + if (_pending_queue.empty()) + { + _mutex_p.unlock(); + break; + } + + Connection::PrivatePList pending_queue_copy(_pending_queue); + _mutex_p.unlock(); + + size_t copy_elem_num(pending_queue_copy.size()); + + dispatch_pending(pending_queue_copy); + //only push_back on list is mandatory! + _mutex_p.lock(); + + Connection::PrivatePList::iterator i, j; + i = _pending_queue.begin(); + size_t counter = 0; + while (counter < copy_elem_num && i != _pending_queue.end()) + { + j = i; + ++j; + _pending_queue.erase(i); + i = j; + ++counter; + } + + _mutex_p.unlock(); + } +} + +void Dispatcher::dispatch_pending(Connection::PrivatePList& pending_queue) +{ // SEEME: dbus-glib is dispatching only one message at a time to not starve the loop/other things... - while (_pending_queue.size() > 0) + _mutex_p_copy.lock(); + while (pending_queue.size() > 0) { Connection::PrivatePList::iterator i, j; - - i = _pending_queue.begin(); - while (i != _pending_queue.end()) + i = pending_queue.begin(); + + while (i != pending_queue.end()) { - j = i; - + j = i; + ++j; if ((*i)->do_dispatch()) - _pending_queue.erase(i); + pending_queue.erase(i); + else + debug_log("dispatch_pending_private: do_dispatch error"); i = j; } } - _mutex_p.unlock(); + _mutex_p_copy.unlock(); } void DBus::_init_threading() |