From 545c32d8e94199bf5d1c44035016dab7320e9cf6 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Mon, 26 Nov 2012 12:19:30 -0600 Subject: [PATCH] Fix long-standing intermittent bug whereby an application using dbus-1-tqt would randomly hang after many hours of continuous operation --- tqdbusconnection_p.h | 5 +++++ tqdbusintegrator.cpp | 24 ++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/tqdbusconnection_p.h b/tqdbusconnection_p.h index cf64c2c..97537f0 100644 --- a/tqdbusconnection_p.h +++ b/tqdbusconnection_p.h @@ -144,6 +144,11 @@ public: }; typedef TQMap PendingCallMap; PendingCallMap pendingCalls; + + typedef TQValueList PendingMessagesForEmit; + PendingMessagesForEmit pendingMessages; + + bool inDispatch; }; #endif diff --git a/tqdbusintegrator.cpp b/tqdbusintegrator.cpp index 373e4a0..55af1e0 100644 --- a/tqdbusintegrator.cpp +++ b/tqdbusintegrator.cpp @@ -273,7 +273,7 @@ int TQT_DBusConnectionPrivate::registerMessageMetaType() TQT_DBusConnectionPrivate::TQT_DBusConnectionPrivate(TQObject *parent) : TQObject(parent), ref(1), mode(InvalidMode), connection(0), server(0), - dispatcher(0) + dispatcher(0), inDispatch(false) { static const int msgType = registerMessageMetaType(); Q_UNUSED(msgType); @@ -452,6 +452,13 @@ void TQT_DBusConnectionPrivate::scheduleDispatch() void TQT_DBusConnectionPrivate::dispatch() { + // dbus_connection_dispatch will hang if called recursively + if (inDispatch) { + printf("[dbus-1-tqt] WARNING: Attempt to call dispatch() recursively was silently ignored to prevent lockup!\n\r"); fflush(stdout); + return; + } + inDispatch = true; + if (mode == ClientMode) { if (dbus_connection_dispatch(connection) != DBUS_DISPATCH_DATA_REMAINS) @@ -460,6 +467,15 @@ void TQT_DBusConnectionPrivate::dispatch() dispatcher->stop(); } } + + inDispatch = false; + + for (TQT_DBusConnectionPrivate::PendingMessagesForEmit::iterator pmfe = pendingMessages.begin(); pmfe != pendingMessages.end(); ++pmfe) { + TQT_DBusMessage msg = *pmfe; + pendingMessages.remove(pmfe); + pmfe = pendingMessages.begin(); + dbusSignal(msg); + } } bool TQT_DBusConnectionPrivate::handleObjectCall(DBusMessage *message) @@ -481,7 +497,11 @@ bool TQT_DBusConnectionPrivate::handleSignal(DBusMessage *message) // FIXME-QT4 //return handleSignal(TQString(), msg) | handleSignal(msg.path(), msg); - dbusSignal(msg); + // If dbusSignal(msg) were called here, it could easily cause a lockup as it would enter the TQt3 event loop, + // which could result in arbitrary methods being called while still inside dbus_connection_dispatch. + // Instead, I enqueue the messages here for TQt3 event loop transmission after dbus_connection_dispatch is finished. + pendingMessages.append(msg); + return true; }