1
0
mirror of https://github.com/thp/pyotherside.git synced 2025-01-28 23:52:55 +08:00

Unbox QJSValue from QVariant in the GUI thread to prevent race condition in QML engine

Calling QJSValue::toVariant() can cause QJSValue to call into QML engine. Since
we perform this correction from QPythonWriter thread context, we end up calling
QML engine from non-GUI thread and causing race conditions and crashes.

This change performs the initial unboxing in QPython::call() and passes to
QPythonWriter the actual value of QJSValue in QVariant.

This fixes issue #36.
This commit is contained in:
Daniel Vrátil 2015-02-10 17:17:57 +01:00 committed by Dan Vrátil
parent 5b76536332
commit 1c0be92e41
2 changed files with 15 additions and 3 deletions

View File

@ -242,7 +242,17 @@ QPython::call(QVariant func, QVariant args, QJSValue callback)
if (!callback.isNull() && !callback.isUndefined() && callback.isCallable()) {
cb = new QJSValue(callback);
}
emit process(func, args, cb);
// Unbox QJSValue from QVariant, since QJSValue::toVariant() can cause calls into
// QML engine and we don't want that to happen from non-GUI thread
QVariantList vl = args.toList();
for (int i = 0, c = vl.count(); i < c; ++i) {
QVariant &v = vl[i];
if (v.userType() == qMetaTypeId<QJSValue>()) {
// TODO: Support boxing a QJSValue as reference in Python
v = v.value<QJSValue>().toVariant();
}
}
emit process(func, vl, cb);
}
QVariant

View File

@ -22,6 +22,7 @@
#include "converter.h"
#include <QVariant>
#include <QCoreApplication>
#include <QTime>
#include <QDate>
@ -29,6 +30,7 @@
#include <QJSValue>
#include <QDebug>
#include <QThread>
class QVariantListBuilder : public ListBuilder<QVariant> {
public:
@ -150,8 +152,8 @@ class QVariantConverter : public Converter<QVariant> {
if (userType == qMetaTypeId<PyObjectRef>()) {
return PYOBJECT;
} else if (userType == qMetaTypeId<QJSValue>()) {
// TODO: Support boxing a QJSValue as reference in Python
return type(v.value<QJSValue>().toVariant());
Q_ASSERT(QThread::currentThread() == qApp->thread());
return type(QVariant());
} else {
qDebug() << "Cannot convert:" << v;
return NONE;