mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 17:17:58 +02:00
Fix access-after-delete during enbtity script engine cleanup
This commit is contained in:
parent
ad5b6d0db7
commit
fe8290468d
5 changed files with 26 additions and 4 deletions
10
libraries/script-engine/src/v8/ScriptEngineDebugFlags.h
Normal file
10
libraries/script-engine/src/v8/ScriptEngineDebugFlags.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
//
|
||||||
|
// Created by ksuprynowicz on 14.11.24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OVERTE_SCRIPTENGINEDEBUGFLAGS_H
|
||||||
|
#define OVERTE_SCRIPTENGINEDEBUGFLAGS_H
|
||||||
|
|
||||||
|
#define OVERTE_SCRIPT_USE_AFTER_DELETE_GUARD
|
||||||
|
|
||||||
|
#endif //OVERTE_SCRIPTENGINEDEBUGFLAGS_H
|
|
@ -258,6 +258,13 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager *manager) : ScriptEngine(manager),
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptEngineV8::~ScriptEngineV8() {
|
ScriptEngineV8::~ScriptEngineV8() {
|
||||||
|
// Process remaining events to avoid problems with `deleteLater` calling destructor of script proxies after script engine has been deleted:
|
||||||
|
{
|
||||||
|
QEventLoop loop;
|
||||||
|
loop.processEvents();
|
||||||
|
}
|
||||||
|
// This is necessary for script engines that don't run in ScriptManager::run(), for example entity scripts:
|
||||||
|
disconnectSignalProxies();
|
||||||
deleteUnusedValueWrappers();
|
deleteUnusedValueWrappers();
|
||||||
#ifdef OVERTE_SCRIPT_USE_AFTER_DELETE_GUARD
|
#ifdef OVERTE_SCRIPT_USE_AFTER_DELETE_GUARD
|
||||||
_wasDestroyed = true;
|
_wasDestroyed = true;
|
||||||
|
@ -272,14 +279,14 @@ void ScriptEngineV8::perManagerLoopIterationCleanup() {
|
||||||
void ScriptEngineV8::disconnectSignalProxies() {
|
void ScriptEngineV8::disconnectSignalProxies() {
|
||||||
_signalProxySetLock.lockForRead();
|
_signalProxySetLock.lockForRead();
|
||||||
while (!_signalProxySet.empty()) {
|
while (!_signalProxySet.empty()) {
|
||||||
|
auto proxy = *_signalProxySet.begin();
|
||||||
_signalProxySetLock.unlock();
|
_signalProxySetLock.unlock();
|
||||||
delete *_signalProxySet.begin();
|
delete proxy;
|
||||||
_signalProxySetLock.lockForRead();
|
_signalProxySetLock.lockForRead();
|
||||||
}
|
}
|
||||||
_signalProxySetLock.unlock();
|
_signalProxySetLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ScriptEngineV8::deleteUnusedValueWrappers() {
|
void ScriptEngineV8::deleteUnusedValueWrappers() {
|
||||||
while (!_scriptValueWrappersToDelete.empty()) {
|
while (!_scriptValueWrappersToDelete.empty()) {
|
||||||
auto wrapper = _scriptValueWrappersToDelete.dequeue();
|
auto wrapper = _scriptValueWrappersToDelete.dequeue();
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "libplatform/libplatform.h"
|
#include "libplatform/libplatform.h"
|
||||||
#include "v8.h"
|
#include "v8.h"
|
||||||
|
|
||||||
|
#include "ScriptEngineDebugFlags.h"
|
||||||
#include "../ScriptEngine.h"
|
#include "../ScriptEngine.h"
|
||||||
#include "../ScriptManager.h"
|
#include "../ScriptManager.h"
|
||||||
#include "../ScriptException.h"
|
#include "../ScriptException.h"
|
||||||
|
@ -58,8 +59,6 @@ using ScriptContextV8Pointer = std::shared_ptr<ScriptContextV8Wrapper>;
|
||||||
|
|
||||||
const double GARBAGE_COLLECTION_TIME_LIMIT_S = 1.0;
|
const double GARBAGE_COLLECTION_TIME_LIMIT_S = 1.0;
|
||||||
|
|
||||||
#define OVERTE_SCRIPT_USE_AFTER_DELETE_GUARD
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(ScriptEngine::FunctionSignature)
|
Q_DECLARE_METATYPE(ScriptEngine::FunctionSignature)
|
||||||
|
|
||||||
/// [V8] Implements ScriptEngine for V8 and translates calls for QScriptEngine
|
/// [V8] Implements ScriptEngine for V8 and translates calls for QScriptEngine
|
||||||
|
|
|
@ -1217,7 +1217,9 @@ ScriptSignalV8Proxy::~ScriptSignalV8Proxy() {
|
||||||
_objectLifetime.Reset();
|
_objectLifetime.Reset();
|
||||||
_v8Context.Reset();
|
_v8Context.Reset();
|
||||||
#ifdef OVERTE_SCRIPT_USE_AFTER_DELETE_GUARD
|
#ifdef OVERTE_SCRIPT_USE_AFTER_DELETE_GUARD
|
||||||
|
Q_ASSERT(!_wasDeleted);
|
||||||
Q_ASSERT(!_engine->_wasDestroyed);
|
Q_ASSERT(!_engine->_wasDestroyed);
|
||||||
|
_wasDeleted = true;
|
||||||
#endif
|
#endif
|
||||||
_engine->_signalProxySetLock.lockForWrite();
|
_engine->_signalProxySetLock.lockForWrite();
|
||||||
_engine->_signalProxySet.remove(this);
|
_engine->_signalProxySet.remove(this);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <QtCore/QPointer>
|
#include <QtCore/QPointer>
|
||||||
#include <QtCore/QString>
|
#include <QtCore/QString>
|
||||||
|
|
||||||
|
#include "ScriptEngineDebugFlags.h"
|
||||||
#include "../ScriptEngine.h"
|
#include "../ScriptEngine.h"
|
||||||
#include "../Scriptable.h"
|
#include "../Scriptable.h"
|
||||||
#include "ScriptEngineV8.h"
|
#include "ScriptEngineV8.h"
|
||||||
|
@ -295,6 +296,9 @@ private: // storage
|
||||||
// Call counter for debugging purposes. It can be used to determine which signals are overwhelming script engine.
|
// Call counter for debugging purposes. It can be used to determine which signals are overwhelming script engine.
|
||||||
int _callCounter{0};
|
int _callCounter{0};
|
||||||
float _totalCallTime_s{ 0.0 };
|
float _totalCallTime_s{ 0.0 };
|
||||||
|
#ifdef OVERTE_SCRIPT_USE_AFTER_DELETE_GUARD
|
||||||
|
std::atomic<bool> _wasDeleted{false};
|
||||||
|
#endif
|
||||||
|
|
||||||
Q_DISABLE_COPY(ScriptSignalV8Proxy)
|
Q_DISABLE_COPY(ScriptSignalV8Proxy)
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue