summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2016-12-26 14:23:39 -0200
committerThiago Macieira <thiago.macieira@intel.com>2017-01-03 13:28:24 +0000
commit9449325f2b234981a2ecc1b0a0bd6ec74f30ff6c (patch)
treeefa24eb387517e777cca85430f17f4f217aeb1ae
parente2ab9322769856fb03ca1f0f24408a3abb8bd38a (diff)
Partially revert "Windows: stop using _beginthreadex on regular builds"
This pertially reverts commit 3ec57107cedb154f256e3ad001ea5475cc64fa94 and brings back the hack to prevent the DLL from being unloaded. It should have been enough, but we've got reports that it's still causing trouble. Since it causes not much harm to keep the DLL loaded (worst case scenario is that QtDBus and QtCore remain loaded after a plugin gets unloaded), we'll keep it. Note: Microsoft is aware that their way of killing threads on process exit is a flaw. See https://blogs.msdn.microsoft.com/oldnewthing/20070502-00/?p=27023/ Task-number: QTBUG-53031 Change-Id: I2962773739e34633b033fffd1493dce695b008c0 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
-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 f95cc3a15d..da7557d7e8 100644
--- a/src/dbus/qdbusconnection.cpp
+++ b/src/dbus/qdbusconnection.cpp
@@ -69,6 +69,10 @@
QT_BEGIN_NAMESPACE
+#ifdef Q_OS_WIN
+static void preventDllUnload();
+#endif
+
Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager)
struct QDBusConnectionManager::ConnectionRequestData
@@ -139,6 +143,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();
}
@@ -1262,4 +1270,31 @@ QByteArray QDBusConnection::localMachineId()
QT_END_NAMESPACE
+#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