Fixed list item removal during access bug

This commit is contained in:
ksuprynowicz 2022-08-12 00:39:45 +02:00
parent 4d61d4fe67
commit ece2b8096b
2 changed files with 33 additions and 15 deletions

View file

@ -4,6 +4,7 @@
// //
// Created by Heather Anderson on 12/5/21. // Created by Heather Anderson on 12/5/21.
// Copyright 2021 Vircadia contributors. // Copyright 2021 Vircadia contributors.
// Copyright 2022 Overte e.V.
// //
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -589,7 +590,14 @@ int ScriptSignalQtProxy::qt_metacall(QMetaObject::Call call, int id, void** argu
args.append(_engine->castVariantToValue(argValue)); args.append(_engine->castVariantToValue(argValue));
} }
QList<Connection> connections;
withReadLock([&]{
for (ConnectionList::iterator iter = _connections.begin(); iter != _connections.end(); ++iter) { for (ConnectionList::iterator iter = _connections.begin(); iter != _connections.end(); ++iter) {
connections.push_back(*iter);
}
});
for (ConnectionList::iterator iter = connections.begin(); iter != connections.end(); ++iter) {
Connection& conn = *iter; Connection& conn = *iter;
conn.callback.call(conn.thisValue, args); conn.callback.call(conn.thisValue, args);
} }
@ -602,15 +610,17 @@ int ScriptSignalQtProxy::discoverMetaCallIdx() {
return ourMeta->methodCount(); return ourMeta->methodCount();
} }
ScriptSignalQtProxy::ConnectionList::iterator ScriptSignalQtProxy::findConnection(QScriptValue thisObject, ScriptSignalQtProxy::ConnectionList::iterator ScriptSignalQtProxy::findConnection(QScriptValue thisObject, QScriptValue callback) {
QScriptValue callback) { ConnectionList::iterator iter;
for (ConnectionList::iterator iter = _connections.begin(); iter != _connections.end(); ++iter) { withReadLock([&]{
for (iter = _connections.begin(); iter != _connections.end(); ++iter) {
Connection& conn = *iter; Connection& conn = *iter;
if (conn.callback.strictlyEquals(callback) && conn.thisValue.strictlyEquals(thisObject)) { if (conn.callback.strictlyEquals(callback) && conn.thisValue.strictlyEquals(thisObject)) {
break;
}
}
});
return iter; return iter;
}
}
return _connections.end();
} }
@ -660,7 +670,10 @@ void ScriptSignalQtProxy::connect(QScriptValue arg0, QScriptValue arg1) {
Connection newConn; Connection newConn;
newConn.callback = callback; newConn.callback = callback;
newConn.thisValue = callbackThis; newConn.thisValue = callbackThis;
withWriteLock([&]{
_connections.append(newConn); _connections.append(newConn);
});
// inform Qt that we're connecting to this signal // inform Qt that we're connecting to this signal
if (!_isConnected) { if (!_isConnected) {
@ -700,7 +713,9 @@ void ScriptSignalQtProxy::disconnect(QScriptValue arg0, QScriptValue arg1) {
} }
// remove it from our internal list of connections // remove it from our internal list of connections
withReadLock([&]{
_connections.erase(lookup); _connections.erase(lookup);
});
// remove a reference to ourselves from the destination callback // remove a reference to ourselves from the destination callback
QScriptValue destData = callback.data(); QScriptValue destData = callback.data();

View file

@ -4,6 +4,7 @@
// //
// Created by Heather Anderson on 12/5/21. // Created by Heather Anderson on 12/5/21.
// Copyright 2021 Vircadia contributors. // Copyright 2021 Vircadia contributors.
// Copyright 2022 Overte e.V.
// //
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -28,6 +29,8 @@
#include "../ScriptEngine.h" #include "../ScriptEngine.h"
#include "ScriptEngineQtScript.h" #include "ScriptEngineQtScript.h"
#include <shared/ReadWriteLockable.h>
class ScriptEngineQtScript; class ScriptEngineQtScript;
class ScriptSignalQtProxy; class ScriptSignalQtProxy;
@ -171,7 +174,7 @@ public: // API
Q_INVOKABLE virtual void disconnect(QScriptValue arg0, QScriptValue arg1 = QScriptValue()) = 0; Q_INVOKABLE virtual void disconnect(QScriptValue arg0, QScriptValue arg1 = QScriptValue()) = 0;
}; };
class ScriptSignalQtProxy final : public ScriptSignalQtProxyBase { class ScriptSignalQtProxy final : public ScriptSignalQtProxyBase, public ReadWriteLockable {
private: // storage private: // storage
struct Connection { struct Connection {
QScriptValue thisValue; QScriptValue thisValue;