summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Volz <andreas@er00923n.fritz.box>2011-11-28 08:23:32 +0100
committerAndreas Volz <andreas@er00923n.fritz.box>2011-11-28 08:23:32 +0100
commit82c63b289d359bf1b2255ba4e721e69118d26fb4 (patch)
tree8c1490cacb3236cf7ad2f2126a41850886e74186
parentd1ec2544d52df89daa0415a755271a8c0e4b35e7 (diff)
downloaddbus-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.h3
-rw-r--r--src/dispatcher.cpp56
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()