History

Add locks around read/writes of _scriptEnginesHash

Ryan Huffman committed 10 years ago

Commit 4bfce761 parent 4dbfd3b2 files · +76 −36Browse files

Showing the changes to interface/src/Application.cpp (1 of 2 files). Show all

Unified · Split

interface/src/Application.cpp+75−36
@@ -4259,10 +4259,13 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser · 4258 unmodified lines
42594259
42604260 QUrl scriptUrl(scriptFilename);
42614261 const QString& scriptURLString = scriptUrl.toString();
4262− if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor
4263− && !_scriptEnginesHash[scriptURLString]->isFinished()) {
4262+ {
4263+ QReadLocker lock(&_scriptEnginesHashLock);
4264+ if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor
4265+ && !_scriptEnginesHash[scriptURLString]->isFinished()) {
42644266
4265− return _scriptEnginesHash[scriptURLString];
4267+ return _scriptEnginesHash[scriptURLString];
4268+ }
42664269 }
42674270
42684271 ScriptEngine* scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface);
@@ -4302,7 +4305,11 @@ void Application::reloadScript(const QString& scriptName, bool isUserLoaded) { · 33 unmodified lines
43024305 void Application::handleScriptEngineLoaded(const QString& scriptFilename) {
43034306 ScriptEngine* scriptEngine = qobject_cast<ScriptEngine*>(sender());
43044307
4305− _scriptEnginesHash.insertMulti(scriptFilename, scriptEngine);
4308+ {
4309+ QWriteLocker lock(&_scriptEnginesHashLock);
4310+ _scriptEnginesHash.insertMulti(scriptFilename, scriptEngine);
4311+ }
4312+
43064313 _runningScriptsWidget->setRunningScripts(getRunningScripts());
43074314 UserActivityLogger::getInstance().loadedScript(scriptFilename);
43084315
@@ -4317,55 +4324,86 @@ void Application::handleScriptLoadError(const QString& scriptFilename) { · 8 unmodified lines
43174324 QMessageBox::warning(getWindow(), "Error Loading Script", scriptFilename + " failed to load.");
43184325 }
43194326
4320−void Application::scriptFinished(const QString& scriptName) {
4321− const QString& scriptURLString = QUrl(scriptName).toString();
4322− QHash<QString, ScriptEngine*>::iterator it = _scriptEnginesHash.find(scriptURLString);
4323− if (it != _scriptEnginesHash.end()) {
4324− _scriptEnginesHash.erase(it);
4327+QStringList Application::getRunningScripts() {
4328+ QReadLocker lock(&_scriptEnginesHashLock);
4329+ return _scriptEnginesHash.keys();
4330+}
4331+
4332+ScriptEngine* Application::getScriptEngine(const QString& scriptHash) {
4333+ QReadLocker lock(&_scriptEnginesHashLock);
4334+ return _scriptEnginesHash.value(scriptHash, nullptr);
4335+}
4336+
4337+void Application::scriptFinished(const QString& scriptName, ScriptEngine* engine) {
4338+ bool removed = false;
4339+ {
4340+ QWriteLocker lock(&_scriptEnginesHashLock);
4341+ const QString& scriptURLString = QUrl(scriptName).toString();
4342+ for (auto it = _scriptEnginesHash.find(scriptURLString); it != _scriptEnginesHash.end(); ++it) {
4343+ if (it.value() == engine) {
4344+ _scriptEnginesHash.erase(it);
4345+ removed = true;
4346+ break;
4347+ }
4348+ }
4349+ }
4350+ postLambdaEvent([this, scriptName]() {
43254351 _runningScriptsWidget->scriptStopped(scriptName);
43264352 _runningScriptsWidget->setRunningScripts(getRunningScripts());
4327− }
4353+ });
43284354 }
43294355
43304356 void Application::stopAllScripts(bool restart) {
4331− if (restart) {
4332− // Delete all running scripts from cache so that they are re-downloaded when they are restarted
4333− auto scriptCache = DependencyManager::get<ScriptCache>();
4334− for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
4357+ {
4358+ QReadLocker lock(&_scriptEnginesHashLock);
4359+
4360+ if (restart) {
4361+ // Delete all running scripts from cache so that they are re-downloaded when they are restarted
4362+ auto scriptCache = DependencyManager::get<ScriptCache>();
4363+ for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
43354364 it != _scriptEnginesHash.constEnd(); it++) {
4336− if (!it.value()->isFinished()) {
4337− scriptCache->deleteScript(it.key());
4365+ if (!it.value()->isFinished()) {
4366+ scriptCache->deleteScript(it.key());
4367+ }
43384368 }
43394369 }
4340− }
43414370
4342− // Stop and possibly restart all currently running scripts
4343− for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
4344− it != _scriptEnginesHash.constEnd(); it++) {
4345− if (it.value()->isFinished()) {
4346− continue;
4347− }
4348− if (restart && it.value()->isUserLoaded()) {
4349− connect(it.value(), SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&)));
4371+ // Stop and possibly restart all currently running scripts
4372+ for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
4373+ it != _scriptEnginesHash.constEnd(); it++) {
4374+ if (it.value()->isFinished()) {
4375+ continue;
4376+ }
4377+ if (restart && it.value()->isUserLoaded()) {
4378+ connect(it.value(), &ScriptEngine::finished, this, [this](QString scriptName, ScriptEngine* engine) {
4379+ reloadScript(scriptName);
4380+ });
4381+ }
4382+ QMetaObject::invokeMethod(it.value(), "stop");
4383+ //it.value()->stop();
4384+ qCDebug(interfaceapp) << "stopping script..." << it.key();
43504385 }
4351− it.value()->stop();
4352− qCDebug(interfaceapp) << "stopping script..." << it.key();
43534386 }
43544387 getMyAvatar()->clearScriptableSettings();
43554388 }
43564389
43574390 bool Application::stopScript(const QString& scriptHash, bool restart) {
43584391 bool stoppedScript = false;
4359− if (_scriptEnginesHash.contains(scriptHash)) {
4360− ScriptEngine* scriptEngine = _scriptEnginesHash[scriptHash];
4361− if (restart) {
4362− auto scriptCache = DependencyManager::get<ScriptCache>();
4363− scriptCache->deleteScript(QUrl(scriptHash));
4364− connect(scriptEngine, SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&)));
4392+ {
4393+ QReadLocker lock(&_scriptEnginesHashLock);
4394+ if (_scriptEnginesHash.contains(scriptHash)) {
4395+ ScriptEngine* scriptEngine = _scriptEnginesHash[scriptHash];
4396+ if (restart) {
4397+ auto scriptCache = DependencyManager::get<ScriptCache>();
4398+ scriptCache->deleteScript(QUrl(scriptHash));
4399+ connect(scriptEngine, &ScriptEngine::finished, this, [this](QString scriptName, ScriptEngine* engine) {
4400+ reloadScript(scriptName);
4401+ });
4402+ }
4403+ scriptEngine->stop();
4404+ stoppedScript = true;
4405+ qCDebug(interfaceapp) << "stopping script..." << scriptHash;
43654406 }
4366− scriptEngine->stop();
4367− stoppedScript = true;
4368− qCDebug(interfaceapp) << "stopping script..." << scriptHash;
43694407 }
43704408 if (_scriptEnginesHash.empty()) {
43714409 getMyAvatar()->clearScriptableSettings();
@@ -4384,6 +4422,7 @@ void Application::reloadOneScript(const QString& scriptName) { · 12 unmodified lines
43844422 }
43854423
43864424 void Application::loadDefaultScripts() {
4425+ QReadLocker lock(&_scriptEnginesHashLock);
43874426 if (!_scriptEnginesHash.contains(DEFAULT_SCRIPTS_JS_URL)) {
43884427 loadScript(DEFAULT_SCRIPTS_JS_URL);
43894428 }