diff options
Diffstat (limited to 'src/dbus/qdbusconnection.cpp')
-rw-r--r-- | src/dbus/qdbusconnection.cpp | 46 |
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 |