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
4259 4259
4260 QUrl scriptUrl(scriptFilename);4260 QUrl scriptUrl(scriptFilename);
4261 const QString& scriptURLString = scriptUrl.toString();4261 const QString& scriptURLString = scriptUrl.toString();
4262 if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor4262 {
4263 && !_scriptEnginesHash[scriptURLString]->isFinished()) {4263 QReadLocker lock(&_scriptEnginesHashLock);
4264 if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor
4265 && !_scriptEnginesHash[scriptURLString]->isFinished()) {
4264 4266
4265 return _scriptEnginesHash[scriptURLString];4267 return _scriptEnginesHash[scriptURLString];
4268 }
4266 }4269 }
4267 4270
4268 ScriptEngine* scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface);4271 ScriptEngine* scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface);
@@ -4302,7 +4305,11 @@ void Application::reloadScript(const QString& scriptName, bool isUserLoaded) { · 33 unmodified lines
4302void Application::handleScriptEngineLoaded(const QString& scriptFilename) {4305void Application::handleScriptEngineLoaded(const QString& scriptFilename) {
4303 ScriptEngine* scriptEngine = qobject_cast<ScriptEngine*>(sender());4306 ScriptEngine* scriptEngine = qobject_cast<ScriptEngine*>(sender());
4304 4307
4305 _scriptEnginesHash.insertMulti(scriptFilename, scriptEngine);4308 {
4309 QWriteLocker lock(&_scriptEnginesHashLock);
4310 _scriptEnginesHash.insertMulti(scriptFilename, scriptEngine);
4311 }
4312
4306 _runningScriptsWidget->setRunningScripts(getRunningScripts());4313 _runningScriptsWidget->setRunningScripts(getRunningScripts());
4307 UserActivityLogger::getInstance().loadedScript(scriptFilename);4314 UserActivityLogger::getInstance().loadedScript(scriptFilename);
4308 4315
@@ -4317,55 +4324,86 @@ void Application::handleScriptLoadError(const QString& scriptFilename) { · 8 unmodified lines
4317 QMessageBox::warning(getWindow(), "Error Loading Script", scriptFilename + " failed to load.");4324 QMessageBox::warning(getWindow(), "Error Loading Script", scriptFilename + " failed to load.");
4318}4325}
4319 4326
4320void Application::scriptFinished(const QString& scriptName) {4327QStringList Application::getRunningScripts() {
4321 const QString& scriptURLString = QUrl(scriptName).toString();4328 QReadLocker lock(&_scriptEnginesHashLock);
4322 QHash<QString, ScriptEngine*>::iterator it = _scriptEnginesHash.find(scriptURLString);4329 return _scriptEnginesHash.keys();
4323 if (it != _scriptEnginesHash.end()) {4330}
4324 _scriptEnginesHash.erase(it);4331
4332ScriptEngine* Application::getScriptEngine(const QString& scriptHash) {
4333 QReadLocker lock(&_scriptEnginesHashLock);
4334 return _scriptEnginesHash.value(scriptHash, nullptr);
4335}
4336
4337void 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]() {
4325 _runningScriptsWidget->scriptStopped(scriptName);4351 _runningScriptsWidget->scriptStopped(scriptName);
4326 _runningScriptsWidget->setRunningScripts(getRunningScripts());4352 _runningScriptsWidget->setRunningScripts(getRunningScripts());
4327 }4353 });
4328}4354}
4329 4355
4330void Application::stopAllScripts(bool restart) {4356void Application::stopAllScripts(bool restart) {
4331 if (restart) {4357 {
4332 // Delete all running scripts from cache so that they are re-downloaded when they are restarted4358 QReadLocker lock(&_scriptEnginesHashLock);
4333 auto scriptCache = DependencyManager::get<ScriptCache>();4359
4334 for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();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();
4335 it != _scriptEnginesHash.constEnd(); it++) {4364 it != _scriptEnginesHash.constEnd(); it++) {
4336 if (!it.value()->isFinished()) {4365 if (!it.value()->isFinished()) {
4337 scriptCache->deleteScript(it.key());4366 scriptCache->deleteScript(it.key());
4367 }
4338 }4368 }
4339 }4369 }
4340 }
4341 4370
4342 // Stop and possibly restart all currently running scripts4371 // Stop and possibly restart all currently running scripts
4343 for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();4372 for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
4344 it != _scriptEnginesHash.constEnd(); it++) {4373 it != _scriptEnginesHash.constEnd(); it++) {
4345 if (it.value()->isFinished()) {4374 if (it.value()->isFinished()) {
4346 continue;4375 continue;
4347 }4376 }
4348 if (restart && it.value()->isUserLoaded()) {4377 if (restart && it.value()->isUserLoaded()) {
4349 connect(it.value(), SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&)));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();
4350 }4385 }
4351 it.value()->stop();
4352 qCDebug(interfaceapp) << "stopping script..." << it.key();
4353 }4386 }
4354 getMyAvatar()->clearScriptableSettings();4387 getMyAvatar()->clearScriptableSettings();
4355}4388}
4356 4389
4357bool Application::stopScript(const QString& scriptHash, bool restart) {4390bool Application::stopScript(const QString& scriptHash, bool restart) {
4358 bool stoppedScript = false;4391 bool stoppedScript = false;
4359 if (_scriptEnginesHash.contains(scriptHash)) {4392 {
4360 ScriptEngine* scriptEngine = _scriptEnginesHash[scriptHash];4393 QReadLocker lock(&_scriptEnginesHashLock);
4361 if (restart) {4394 if (_scriptEnginesHash.contains(scriptHash)) {
4362 auto scriptCache = DependencyManager::get<ScriptCache>();4395 ScriptEngine* scriptEngine = _scriptEnginesHash[scriptHash];
4363 scriptCache->deleteScript(QUrl(scriptHash));4396 if (restart) {
4364 connect(scriptEngine, SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&)));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;
4365 }4406 }
4366 scriptEngine->stop();
4367 stoppedScript = true;
4368 qCDebug(interfaceapp) << "stopping script..." << scriptHash;
4369 }4407 }
4370 if (_scriptEnginesHash.empty()) {4408 if (_scriptEnginesHash.empty()) {
4371 getMyAvatar()->clearScriptableSettings();4409 getMyAvatar()->clearScriptableSettings();
@@ -4384,6 +4422,7 @@ void Application::reloadOneScript(const QString& scriptName) { · 12 unmodified lines
4384}4422}
4385 4423
4386void Application::loadDefaultScripts() {4424void Application::loadDefaultScripts() {
4425 QReadLocker lock(&_scriptEnginesHashLock);
4387 if (!_scriptEnginesHash.contains(DEFAULT_SCRIPTS_JS_URL)) {4426 if (!_scriptEnginesHash.contains(DEFAULT_SCRIPTS_JS_URL)) {
4388 loadScript(DEFAULT_SCRIPTS_JS_URL);4427 loadScript(DEFAULT_SCRIPTS_JS_URL);
4389 }4428 }