summaryrefslogtreecommitdiffstats
path: root/src/dbus/qdbusconnection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dbus/qdbusconnection.cpp')
-rw-r--r--src/dbus/qdbusconnection.cpp46
1 files changed, 41 insertions, 5 deletions
diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp
index ea8c2b0311..bd25d8a6bf 100644
--- a/src/dbus/qdbusconnection.cpp
+++ b/src/dbus/qdbusconnection.cpp
@@ -44,6 +44,7 @@
#include <qdebug.h>
#include <qcoreapplication.h>
#include <qstringlist.h>
+#include <qvector.h>
#include <qtimer.h>
#include <qthread.h>
@@ -68,6 +69,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
@@ -156,6 +161,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();
}
@@ -909,8 +918,8 @@ bool QDBusConnection::registerObject(const QString &path, const QString &interfa
if (!d || !d->connection || !object || !options || !QDBusUtil::isValidObjectPath(path))
return false;
- QStringList pathComponents = path.split(QLatin1Char('/'));
- if (pathComponents.last().isEmpty())
+ auto pathComponents = path.splitRef(QLatin1Char('/'));
+ if (pathComponents.constLast().isEmpty())
pathComponents.removeLast();
QDBusWriteLocker locker(RegisterObjectAction, d);
@@ -965,7 +974,7 @@ bool QDBusConnection::registerObject(const QString &path, const QString &interfa
}
} else {
// add entry
- node = node->children.insert(it, pathComponents.at(i));
+ node = node->children.insert(it, pathComponents.at(i).toString());
}
// iterate
@@ -1017,8 +1026,8 @@ QObject *QDBusConnection::objectRegisteredAt(const QString &path) const
if (!d || !d->connection || !QDBusUtil::isValidObjectPath(path))
return 0;
- QStringList pathComponents = path.split(QLatin1Char('/'));
- if (pathComponents.last().isEmpty())
+ auto pathComponents = path.splitRef(QLatin1Char('/'));
+ if (pathComponents.constLast().isEmpty())
pathComponents.removeLast();
// lower-bound search for where this object should enter in the tree
@@ -1281,4 +1290,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