forked from gentoo/gentoo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
dev-qt/qtcore: QLibrary: fix deadlock caused by fix to QTBUG-39642
See also: https://bugreports.qt.io/browse/QTBUG-83207 Package-Manager: Portage-2.3.96, Repoman-2.3.22 Signed-off-by: Andreas Sturmlechner <[email protected]>
- Loading branch information
Showing
1 changed file
with
106 additions
and
0 deletions.
There are no files selected for viewing
106 changes: 106 additions & 0 deletions
106
dev-qt/qtcore/files/qtcore-5.14.2-QLibrary-deadlock.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
From 276fa8383a7535765be7182883ef4aade17ce013 Mon Sep 17 00:00:00 2001 | ||
From: Thiago Macieira <[email protected]> | ||
Date: Thu, 2 Apr 2020 12:08:41 -0300 | ||
Subject: [PATCH] QLibrary: fix deadlock caused by fix to QTBUG-39642 | ||
|
||
Commit ae6f73e8566fa76470937aca737141183929a5ec inserted a mutex around | ||
the entire load_sys(). We had reasoed that deadlocks would only occur if | ||
the object creation in instance() recursed into its own instance(), | ||
which was already a bug. But we had forgotten that dlopen()/ | ||
LoadLibrary() executes initialization code from the module being loaded, | ||
which could cause a recursion back into the same QPluginLoader or | ||
QLibrary object. This recursion is benign because the module *is* loaded | ||
and dlopen()/LoadLibrary() returns the same handle. | ||
|
||
[ChangeLog][QtCore][QLibrary and QPluginLoader] Fixed a deadlock that | ||
would happen if the plugin or library being loaded has load-time | ||
initialization code (C++ global variables) that recursed back into the | ||
same QLibrary or QPluginLoader object. | ||
|
||
PS: QLibraryPrivate::loadPlugin() updates pluginState outside a mutex | ||
lock, so pluginState should be made an atomic variable. Once that is | ||
done, we'll only need locking the mutex to update errorString (no | ||
locking before loading). | ||
|
||
Fixes: QTBUG-83207 | ||
Task-number: QTBUG-39642 | ||
Change-Id: Ibdc95e9af7bd456a94ecfffd160209304e5ab2eb | ||
Reviewed-by: Volker Hilsheimer <[email protected]> | ||
Reviewed-by: David Faure <[email protected]> | ||
--- | ||
src/corelib/plugin/qlibrary.cpp | 2 -- | ||
src/corelib/plugin/qlibrary_unix.cpp | 4 ++++ | ||
src/corelib/plugin/qlibrary_win.cpp | 3 +++ | ||
3 files changed, 7 insertions(+), 2 deletions(-) | ||
|
||
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp | ||
index ddb053c26fa..be9d92b2048 100644 | ||
--- a/src/corelib/plugin/qlibrary.cpp | ||
+++ b/src/corelib/plugin/qlibrary.cpp | ||
@@ -576,9 +576,7 @@ bool QLibraryPrivate::load() | ||
|
||
Q_TRACE(QLibraryPrivate_load_entry, fileName); | ||
|
||
- mutex.lock(); | ||
bool ret = load_sys(); | ||
- mutex.unlock(); | ||
if (qt_debug_component()) { | ||
if (ret) { | ||
qDebug() << "loaded library" << fileName; | ||
diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp | ||
index 017aa97b66a..a5c72f81d96 100644 | ||
--- a/src/corelib/plugin/qlibrary_unix.cpp | ||
+++ b/src/corelib/plugin/qlibrary_unix.cpp | ||
@@ -123,6 +123,7 @@ QStringList QLibraryPrivate::prefixes_sys() | ||
|
||
bool QLibraryPrivate::load_sys() | ||
{ | ||
+ QMutexLocker locker(&mutex); | ||
QString attempt; | ||
QFileSystemEntry fsEntry(fileName); | ||
|
||
@@ -213,6 +214,7 @@ bool QLibraryPrivate::load_sys() | ||
} | ||
#endif | ||
|
||
+ locker.unlock(); | ||
bool retry = true; | ||
Handle hnd = nullptr; | ||
for (int prefix = 0; retry && !hnd && prefix < prefixes.size(); prefix++) { | ||
@@ -273,6 +275,8 @@ bool QLibraryPrivate::load_sys() | ||
} | ||
} | ||
#endif | ||
+ | ||
+ locker.relock(); | ||
if (!hnd) { | ||
errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName, qdlerror()); | ||
} | ||
diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp | ||
index 000bf762763..ef58724be8e 100644 | ||
--- a/src/corelib/plugin/qlibrary_win.cpp | ||
+++ b/src/corelib/plugin/qlibrary_win.cpp | ||
@@ -78,6 +78,7 @@ bool QLibraryPrivate::load_sys() | ||
// fileName | ||
// | ||
// NB If it's a plugin we do not ever try the ".dll" extension | ||
+ QMutexLocker locker(&mutex); | ||
QStringList attempts; | ||
|
||
if (pluginState != IsAPlugin) | ||
@@ -95,6 +96,7 @@ bool QLibraryPrivate::load_sys() | ||
attempts.prepend(QDir::rootPath() + fileName); | ||
#endif | ||
|
||
+ locker.unlock(); | ||
Handle hnd = nullptr; | ||
for (const QString &attempt : qAsConst(attempts)) { | ||
#ifndef Q_OS_WINRT | ||
@@ -115,6 +117,7 @@ bool QLibraryPrivate::load_sys() | ||
#ifndef Q_OS_WINRT | ||
SetErrorMode(oldmode); | ||
#endif | ||
+ locker.relock(); | ||
if (!hnd) { | ||
errorString = QLibrary::tr("Cannot load library %1: %2").arg( | ||
QDir::toNativeSeparators(fileName), qt_error_string()); |