summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2016-04-27 23:44:57 -0700
committerRoland Winklmeier <Roland.M.Winklmeier@gmail.com>2016-05-02 20:24:24 +0000
commitfecaa6aae83a3ffa8f1fd41c5aa8275a1bfa7c9b (patch)
tree895a0be810b6dd8b18122844ac454ca380e360bc
parent22a7edd816b417daf43e3b4c4f0257fbc3ad7921 (diff)
Workaround Windows DLL unload issue with threads running
We don't know why it happens, so let's apply a workaround. See the comment for more details. Task-number: QTBUG-53031 Change-Id: Ifea6e497f11a461db432ffff144972e892fbbda5 Reviewed-by: Roland Winklmeier <Roland.M.Winklmeier@gmail.com> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/dbus/qdbusconnection.cpp35
1 files changed, 35 insertions, 0 deletions
diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp
index 34b3da7df3..7cdacc1284 100644
--- a/src/dbus/qdbusconnection.cpp
+++ b/src/dbus/qdbusconnection.cpp
@@ -62,6 +62,10 @@
QT_BEGIN_NAMESPACE
+#ifdef Q_OS_WIN
+static void preventDllUnload();
+#endif
+
Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager)
// can be replaced with a lambda in Qt 5.7
@@ -150,6 +154,10 @@ QDBusConnectionManager::QDBusConnectionManager()
this, &QDBusConnectionManager::createServer, Qt::BlockingQueuedConnection);
moveToThread(this); // ugly, don't do this in other projects
+#ifdef Q_OS_WIN
+ // prevent the library from being unloaded on Windows. See comments in the function.
+ preventDllUnload();
+#endif
defaultBuses[0] = defaultBuses[1] = Q_NULLPTR;
start();
}
@@ -1275,4 +1283,31 @@ QT_END_NAMESPACE
#include "qdbusconnection.moc"
+#ifdef Q_OS_WIN
+# include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+static void preventDllUnload()
+{
+ // Thread termination is really wacky on Windows. For some reason we don't
+ // understand, exiting from the thread may try to unload the DLL. Since the
+ // QDBusConnectionManager thread runs until the DLL is unloaded, we've got
+ // a deadlock: the main thread is waiting for the manager thread to exit,
+ // but the manager thread is attempting to acquire a lock to unload the DLL.
+ //
+ // We work around the issue by preventing the unload from happening in the
+ // first place.
+ //
+ // For this trick, see
+ // https://blogs.msdn.microsoft.com/oldnewthing/20131105-00/?p=2733
+
+ static HMODULE self;
+ GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
+ GET_MODULE_HANDLE_EX_FLAG_PIN,
+ reinterpret_cast<const wchar_t *>(&self), // any address in this DLL
+ &self);
+}
+QT_END_NAMESPACE
+#endif
+
#endif // QT_NO_DBUS