add support to abort evaluation of long running scripts on shutdown
Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 2 files). Show all
Unified · Split
| @@ -140,6 +140,8 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam · 139 unmodified lines | |||
| 140 | connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) { | 140 | connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) { |
| 141 | hadUncaughtExceptions(*this, _fileNameString); | 141 | hadUncaughtExceptions(*this, _fileNameString); |
| 142 | }); | 142 | }); |
| 143 | |||
| 144 | setProcessEventsInterval(MSECS_PER_SECOND); | ||
| 143 | } | 145 | } |
| 144 | 146 | ||
| 145 | ScriptEngine::~ScriptEngine() { | 147 | ScriptEngine::~ScriptEngine() { |
| @@ -198,9 +200,28 @@ void ScriptEngine::waitTillDoneRunning() { · 52 unmodified lines | |||
| 198 | // we want the application thread to continue to process events, because the scripts will likely need to | 200 | // we want the application thread to continue to process events, because the scripts will likely need to |
| 199 | // marshall messages across to the main thread. For example if they access Settings or Menu in any of their | 201 | // marshall messages across to the main thread. For example if they access Settings or Menu in any of their |
| 200 | // shutdown code. | 202 | // shutdown code. |
| 203 | QString scriptName = getFilename(); | ||
| 204 | |||
| 205 | auto startedWaiting = usecTimestampNow(); | ||
| 201 | while (thread()->isRunning()) { | 206 | while (thread()->isRunning()) { |
| 202 | // process events for the main application thread, allowing invokeMethod calls to pass between threads | 207 | // process events for the main application thread, allowing invokeMethod calls to pass between threads |
| 203 | QCoreApplication::processEvents(); | 208 | QCoreApplication::processEvents(); |
| 209 | auto stillWaiting = usecTimestampNow(); | ||
| 210 | auto elapsedUsecs = stillWaiting - startedWaiting; | ||
| 211 | |||
| 212 | // if we've been waiting a second or more, then tell the script engine to stop evaluating | ||
| 213 | static const auto MAX_SCRIPT_EVALUATION_TIME = USECS_PER_SECOND; | ||
| 214 | static const auto WAITING_TOO_LONG = MAX_SCRIPT_EVALUATION_TIME * 5; | ||
| 215 | |||
| 216 | // if we've been waiting for more than 5 seconds then we should be more aggessive about stopping | ||
| 217 | if (elapsedUsecs > WAITING_TOO_LONG) { | ||
| 218 | qCDebug(scriptengine) << "Script " << scriptName << " has been running too long [" << elapsedUsecs << " usecs] quitting."; | ||
| 219 | thread()->quit(); | ||
| 220 | break; | ||
| 221 | } else if (elapsedUsecs > MAX_SCRIPT_EVALUATION_TIME) { | ||
| 222 | qCDebug(scriptengine) << "Script " << scriptName << " has been running too long [" << elapsedUsecs << " usecs] aborting evaluation."; | ||
| 223 | QMetaObject::invokeMethod(this, "abortEvaluation"); | ||
| 224 | } | ||
| 204 | } | 225 | } |
| 205 | } | 226 | } |
| 206 | } | 227 | } |
| @@ -411,7 +432,6 @@ void ScriptEngine::registerValue(const QString& valueName, QScriptValue value) { · 204 unmodified lines | |||
| 411 | if (partsToGo > 0) { | 432 | if (partsToGo > 0) { |
| 412 | //QObject *object = new QObject; | 433 | //QObject *object = new QObject; |
| 413 | QScriptValue partValue = newArray(); //newQObject(object, QScriptEngine::ScriptOwnership); | 434 | QScriptValue partValue = newArray(); //newQObject(object, QScriptEngine::ScriptOwnership); |
| 414 | qDebug() << "partValue[" << pathPart<<"].isArray() :" << partValue.isArray(); | ||
| 415 | partObject.setProperty(pathPart, partValue); | 435 | partObject.setProperty(pathPart, partValue); |
| 416 | } else { | 436 | } else { |
| 417 | partObject.setProperty(pathPart, value); | 437 | partObject.setProperty(pathPart, value); |
| @@ -1110,11 +1130,6 @@ void ScriptEngine::loadEntityScript(QWeakPointer<ScriptEngine> theEngine, const · 692 unmodified lines | |||
| 1110 | << QThread::currentThread() << "] expected thread [" << strongEngine->thread() << "]"; | 1130 | << QThread::currentThread() << "] expected thread [" << strongEngine->thread() << "]"; |
| 1111 | #endif | 1131 | #endif |
| 1112 | strongEngine->entityScriptContentAvailable(entityID, scriptOrURL, contents, isURL, success); | 1132 | strongEngine->entityScriptContentAvailable(entityID, scriptOrURL, contents, isURL, success); |
| 1113 | } else { | ||
| 1114 | // FIXME - I'm leaving this in for testing, so that QA can confirm that sometimes the script contents | ||
| 1115 | // returns after the ScriptEngine has been deleted, we can remove this after QA verifies the | ||
| 1116 | // repro case. | ||
| 1117 | qDebug() << "ScriptCache::getScriptContents() returned after our ScriptEngine was deleted... script:" << scriptOrURL; | ||
| 1118 | } | 1133 | } |
| 1119 | }, forceRedownload); | 1134 | }, forceRedownload); |
| 1120 | } | 1135 | } |