aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2022-06-01 12:36:33 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-06-03 21:09:00 +0000
commit210287f9ef2aa2196244097311bef0f285b85ce5 (patch)
tree41a2ce4de0513f6400718e43421684216cf8d42c
parent3c9a995a9cb830757084ae5fb5ebea12a7de1c80 (diff)
libshiboken: Fix occasional crashes when using QML
QML calls into the generated QObject::metaObject() from threads without GIL, causing crashes for example in retrieveWrapper(). Use a mutex to guard access. Change-Id: I374ada7fc207d86a062f950751503764a5e5dddf Reviewed-by: Christian Tismer <tismer@stackless.com> (cherry picked from commit e141ea41cf6f2840281ab6e52b0861a6d1dcc137) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--sources/shiboken6/libshiboken/bindingmanager.cpp12
1 files changed, 12 insertions, 0 deletions
diff --git a/sources/shiboken6/libshiboken/bindingmanager.cpp b/sources/shiboken6/libshiboken/bindingmanager.cpp
index 2d4583495..a9e7028e1 100644
--- a/sources/shiboken6/libshiboken/bindingmanager.cpp
+++ b/sources/shiboken6/libshiboken/bindingmanager.cpp
@@ -49,6 +49,7 @@
#include <cstddef>
#include <fstream>
+#include <mutex>
#include <unordered_map>
namespace Shiboken
@@ -141,6 +142,11 @@ struct BindingManager::BindingManagerPrivate {
using DestructorEntries = std::vector<DestructorEntry>;
WrapperMap wrapperMapper;
+ // Guard wrapperMapper mainly for QML which calls into the generated
+ // QObject::metaObject() and elsewhere from threads without GIL, causing
+ // crashes for example in retrieveWrapper(). std::shared_mutex was rejected due to:
+ // https://stackoverflow.com/questions/50972345/when-is-stdshared-timed-mutex-slower-than-stdmutex-and-when-not-to-use-it
+ std::mutex wrapperMapLock;
Graph classHierarchy;
DestructorEntries deleteInMainThread;
bool destroying;
@@ -156,6 +162,7 @@ bool BindingManager::BindingManagerPrivate::releaseWrapper(void *cptr, SbkObject
// The wrapper argument is checked to ensure that the correct wrapper is released.
// Returns true if the correct wrapper is found and released.
// If wrapper argument is NULL, no such check is performed.
+ std::lock_guard<std::mutex> guard(wrapperMapLock);
auto iter = wrapperMapper.find(cptr);
if (iter != wrapperMapper.end() && (wrapper == nullptr || iter->second == wrapper)) {
wrapperMapper.erase(iter);
@@ -167,6 +174,7 @@ bool BindingManager::BindingManagerPrivate::releaseWrapper(void *cptr, SbkObject
void BindingManager::BindingManagerPrivate::assignWrapper(SbkObject *wrapper, const void *cptr)
{
assert(cptr);
+ std::lock_guard<std::mutex> guard(wrapperMapLock);
auto iter = wrapperMapper.find(cptr);
if (iter == wrapperMapper.end())
wrapperMapper.insert(std::make_pair(cptr, wrapper));
@@ -193,6 +201,7 @@ BindingManager::~BindingManager()
* the BindingManager is being destroyed the interpreter is alredy
* shutting down. */
if (Py_IsInitialized()) { // ensure the interpreter is still valid
+ std::lock_guard<std::mutex> guard(m_d->wrapperMapLock);
while (!m_d->wrapperMapper.empty()) {
Object::destroy(m_d->wrapperMapper.begin()->second, const_cast<void *>(m_d->wrapperMapper.begin()->first));
}
@@ -208,6 +217,7 @@ BindingManager &BindingManager::instance() {
bool BindingManager::hasWrapper(const void *cptr)
{
+ std::lock_guard<std::mutex> guard(m_d->wrapperMapLock);
return m_d->wrapperMapper.find(cptr) != m_d->wrapperMapper.end();
}
@@ -268,6 +278,7 @@ void BindingManager::addToDeletionInMainThread(const DestructorEntry &e)
SbkObject *BindingManager::retrieveWrapper(const void *cptr)
{
+ std::lock_guard<std::mutex> guard(m_d->wrapperMapLock);
auto iter = m_d->wrapperMapper.find(cptr);
if (iter == m_d->wrapperMapper.end())
return nullptr;
@@ -377,6 +388,7 @@ PyTypeObject *BindingManager::resolveType(void **cptr, PyTypeObject *type)
std::set<PyObject *> BindingManager::getAllPyObjects()
{
std::set<PyObject *> pyObjects;
+ std::lock_guard<std::mutex> guard(m_d->wrapperMapLock);
const WrapperMap &wrappersMap = m_d->wrapperMapper;
auto it = wrappersMap.begin();
for (; it != wrappersMap.end(); ++it)