diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 69de067d10..edb482484e 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -356,6 +356,13 @@ QStringList ScriptEngines::getRunningScripts() { void ScriptEngines::stopAllScripts(bool restart) { QVector toReload; QReadLocker lock(&_scriptEnginesHashLock); + + if (_isReloading) { + return; + } else { + _isReloading = true; + } + for (QHash::const_iterator it = _scriptEnginesHash.constBegin(); it != _scriptEnginesHash.constEnd(); it++) { ScriptEngine *scriptEngine = it.value(); @@ -375,7 +382,7 @@ void ScriptEngines::stopAllScripts(bool restart) { } // wait for engines to stop (ie: providing time for .scriptEnding cleanup handlers to run) before // triggering reload of any Client scripts / Entity scripts - QTimer::singleShot(500, this, [=]() { + QTimer::singleShot(1000, this, [=]() { for(const auto &scriptName : toReload) { auto scriptEngine = getScriptEngine(scriptName); if (scriptEngine && !scriptEngine->isFinished()) { @@ -390,6 +397,7 @@ void ScriptEngines::stopAllScripts(bool restart) { qCDebug(scriptengine) << "stopAllScripts -- emitting scriptsReloading"; emit scriptsReloading(); } + _isReloading = false; }); } diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 91dc54a0ec..bd2b3858a1 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -112,6 +112,7 @@ protected: ScriptsModel _scriptsModel; ScriptsModelFilter _scriptsModelFilter; std::atomic _isStopped { false }; + std::atomic _isReloading { false }; }; QUrl normalizeScriptURL(const QUrl& rawScriptURL); diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index b045e64c6a..6321c17ded 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -41,7 +41,16 @@ var numStillSnapshotUploadsPending = 0; // It's totally unnecessary to return to C++ to perform many of these requests, such as DELETEing an old story, // POSTING a new one, PUTTING a new audience, or GETTING story data. It's far more efficient to do all of that within JS -var request = Script.require('request').request; +var request; + +try { + // Due to an issue where if the user spams 'script reload', this call could cause an exception + // preventing our scriptEnding to not properly be initialized resulting in the tablet button + // duplicating itself where you end up with a bunch of SNAP buttons on your toolbar + request = Script.require('request').request; +} catch(err) { + print('Failed to resolve request api, error: ' + err); +} function openLoginWindow() { if ((HMD.active && Settings.getValue("hmdTabletBecomesToolbar", false)) @@ -750,11 +759,10 @@ Script.scriptEnding.connect(function () { } if (tablet) { tablet.removeButton(button); + tablet.screenChanged.disconnect(onTabletScreenChanged); } Window.snapshotShared.disconnect(snapshotUploaded); - tablet.screenChanged.disconnect(onTabletScreenChanged); Snapshot.snapshotLocationSet.disconnect(snapshotLocationSet); - Entities.canRezChanged.disconnect(processRezPermissionChange); Entities.canRezTmpChanged.disconnect(processRezPermissionChange); });