mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
Merge pull request #7769 from ZappoMan/abortForInfiniteLoops
add support to abort evaluation of long running scripts on shutdown
This commit is contained in:
commit
ad285ff9a1
2 changed files with 22 additions and 20 deletions
|
@ -140,6 +140,8 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam
|
|||
connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) {
|
||||
hadUncaughtExceptions(*this, _fileNameString);
|
||||
});
|
||||
|
||||
setProcessEventsInterval(MSECS_PER_SECOND);
|
||||
}
|
||||
|
||||
ScriptEngine::~ScriptEngine() {
|
||||
|
@ -198,9 +200,28 @@ void ScriptEngine::waitTillDoneRunning() {
|
|||
// we want the application thread to continue to process events, because the scripts will likely need to
|
||||
// marshall messages across to the main thread. For example if they access Settings or Menu in any of their
|
||||
// shutdown code.
|
||||
QString scriptName = getFilename();
|
||||
|
||||
auto startedWaiting = usecTimestampNow();
|
||||
while (thread()->isRunning()) {
|
||||
// process events for the main application thread, allowing invokeMethod calls to pass between threads
|
||||
QCoreApplication::processEvents();
|
||||
auto stillWaiting = usecTimestampNow();
|
||||
auto elapsedUsecs = stillWaiting - startedWaiting;
|
||||
|
||||
// if we've been waiting a second or more, then tell the script engine to stop evaluating
|
||||
static const auto MAX_SCRIPT_EVALUATION_TIME = USECS_PER_SECOND;
|
||||
static const auto WAITING_TOO_LONG = MAX_SCRIPT_EVALUATION_TIME * 5;
|
||||
|
||||
// if we've been waiting for more than 5 seconds then we should be more aggessive about stopping
|
||||
if (elapsedUsecs > WAITING_TOO_LONG) {
|
||||
qCDebug(scriptengine) << "Script " << scriptName << " has been running too long [" << elapsedUsecs << " usecs] quitting.";
|
||||
thread()->quit();
|
||||
break;
|
||||
} else if (elapsedUsecs > MAX_SCRIPT_EVALUATION_TIME) {
|
||||
qCDebug(scriptengine) << "Script " << scriptName << " has been running too long [" << elapsedUsecs << " usecs] aborting evaluation.";
|
||||
QMetaObject::invokeMethod(this, "abortEvaluation");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -411,7 +432,6 @@ void ScriptEngine::registerValue(const QString& valueName, QScriptValue value) {
|
|||
if (partsToGo > 0) {
|
||||
//QObject *object = new QObject;
|
||||
QScriptValue partValue = newArray(); //newQObject(object, QScriptEngine::ScriptOwnership);
|
||||
qDebug() << "partValue[" << pathPart<<"].isArray() :" << partValue.isArray();
|
||||
partObject.setProperty(pathPart, partValue);
|
||||
} else {
|
||||
partObject.setProperty(pathPart, value);
|
||||
|
@ -1110,11 +1130,6 @@ void ScriptEngine::loadEntityScript(QWeakPointer<ScriptEngine> theEngine, const
|
|||
<< QThread::currentThread() << "] expected thread [" << strongEngine->thread() << "]";
|
||||
#endif
|
||||
strongEngine->entityScriptContentAvailable(entityID, scriptOrURL, contents, isURL, success);
|
||||
} else {
|
||||
// FIXME - I'm leaving this in for testing, so that QA can confirm that sometimes the script contents
|
||||
// returns after the ScriptEngine has been deleted, we can remove this after QA verifies the
|
||||
// repro case.
|
||||
qDebug() << "ScriptCache::getScriptContents() returned after our ScriptEngine was deleted... script:" << scriptOrURL;
|
||||
}
|
||||
}, forceRedownload);
|
||||
}
|
||||
|
|
|
@ -129,20 +129,7 @@ void ScriptEngines::shutdownScripting() {
|
|||
// "entities sandbox" which is only used to evaluate entities scripts to test their validity before using
|
||||
// them. We don't need to stop scripts that aren't running.
|
||||
if (scriptEngine->isRunning()) {
|
||||
|
||||
// If the script is running, but still evaluating then we need to wait for its evaluation step to
|
||||
// complete. After that we can handle the stop process appropriately
|
||||
if (scriptEngine->evaluatePending()) {
|
||||
while (scriptEngine->evaluatePending()) {
|
||||
|
||||
// This event loop allows any started, but not yet finished evaluate() calls to complete
|
||||
// we need to let these complete so that we can be guaranteed that the script engine isn't
|
||||
// in a partially setup state, which can confuse our shutdown unwinding.
|
||||
QEventLoop loop;
|
||||
QObject::connect(scriptEngine, &ScriptEngine::evaluationFinished, &loop, &QEventLoop::quit);
|
||||
loop.exec();
|
||||
}
|
||||
}
|
||||
qCDebug(scriptengine) << "about to shutdown script:" << scriptName;
|
||||
|
||||
// We disconnect any script engine signals from the application because we don't want to do any
|
||||
// extra stopScript/loadScript processing that the Application normally does when scripts start
|
||||
|
|
Loading…
Reference in a new issue