Fix most of the crash causes on script engine reload/shutdown
Showing the changes to libraries/script-engine/src/ScriptManager.cpp (1 of 26 files). Show all
Unified · Split
| @@ -67,6 +67,7 @@ · 66 unmodified lines | ||
| 67 | 67 | #include <AddressManager.h> |
| 68 | 68 | #include <NetworkingConstants.h> |
| 69 | 69 | #include <ThreadHelpers.h> |
| 70 | +#include <iostream> | |
| 70 | 71 | |
| 71 | 72 | const QString ScriptManager::_SETTINGS_ENABLE_EXTENDED_EXCEPTIONS { |
| 72 | 73 | "com.highfidelity.experimental.enableExtendedJSExceptions" |
| @@ -366,7 +367,12 @@ bool ScriptManager::isDebugMode() const { · 293 unmodified lines | ||
| 366 | 367 | #endif |
| 367 | 368 | } |
| 368 | 369 | |
| 369 | −ScriptManager::~ScriptManager() {} | |
| 370 | +ScriptManager::~ScriptManager() { | |
| 371 | + qDebug() << "ScriptManager::~ScriptManager() : Script manager deleted, type: " << _type << " name: " << _fileNameString; | |
| 372 | + if (_type == ScriptManager::Type::ENTITY_CLIENT) { | |
| 373 | + printf("ScriptManager::~ScriptManager"); | |
| 374 | + } | |
| 375 | +} | |
| 370 | 376 | |
| 371 | 377 | void ScriptManager::disconnectNonEssentialSignals() { |
| 372 | 378 | disconnect(); |
| @@ -464,11 +470,14 @@ void ScriptManager::waitTillDoneRunning(bool shutdown) { · 91 unmodified lines | ||
| 464 | 470 | } |
| 465 | 471 | #else |
| 466 | 472 | auto startedWaiting = usecTimestampNow(); |
| 467 | − while (workerThread->isRunning()) { | |
| 473 | + while (!_isDoneRunning) { | |
| 468 | 474 | // If the final evaluation takes too long, then tell the script engine to stop running |
| 469 | 475 | auto elapsedUsecs = usecTimestampNow() - startedWaiting; |
| 476 | + // TODO: This part was very unsafe and was causing crashes all the time. | |
| 477 | + // I disabled it for now until we find a safer solution. | |
| 478 | + // With it disabled now we get clean shutdowns and restarts. | |
| 470 | 479 | // V8TODO: temporarily increased script timeout. Maybe use different timeouts for release and unoptimized debug? |
| 471 | − static const auto MAX_SCRIPT_EVALUATION_TIME = USECS_PER_SECOND; | |
| 480 | + /*static const auto MAX_SCRIPT_EVALUATION_TIME = 10 * USECS_PER_SECOND; | |
| 472 | 481 | if (elapsedUsecs > MAX_SCRIPT_EVALUATION_TIME) { |
| 473 | 482 | workerThread->quit(); |
| 474 | 483 | |
| @@ -485,12 +494,12 @@ void ScriptManager::waitTillDoneRunning(bool shutdown) { · 10 unmodified lines | ||
| 485 | 494 | |
| 486 | 495 | // Wait for the scripting thread to stop running, as |
| 487 | 496 | // flooding it with aborts/exceptions will persist it longer |
| 488 | − static const auto MAX_SCRIPT_QUITTING_TIME = 0.5 * MSECS_PER_SECOND; | |
| 497 | + static const auto MAX_SCRIPT_QUITTING_TIME = 50 * MSECS_PER_SECOND; | |
| 489 | 498 | if (!workerThread->wait(MAX_SCRIPT_QUITTING_TIME)) { |
| 490 | 499 | Q_ASSERT(false); |
| 491 | 500 | workerThread->terminate(); |
| 492 | 501 | } |
| 493 | − } | |
| 502 | + }*/ | |
| 494 | 503 | |
| 495 | 504 | if (shutdown) { |
| 496 | 505 | // NOTE: This will be called on the main application thread (among other threads) from stopAllScripts. |
| @@ -502,7 +511,7 @@ void ScriptManager::waitTillDoneRunning(bool shutdown) { · 5 unmodified lines | ||
| 502 | 511 | } |
| 503 | 512 | |
| 504 | 513 | // Avoid a pure busy wait |
| 505 | − QThread::yieldCurrentThread(); | |
| 514 | + QThread::msleep(1); | |
| 506 | 515 | } |
| 507 | 516 | #endif |
| 508 | 517 | |
| @@ -510,6 +519,11 @@ void ScriptManager::waitTillDoneRunning(bool shutdown) { · 1 unmodified line | ||
| 510 | 519 | } |
| 511 | 520 | } |
| 512 | 521 | |
| 522 | +void ScriptManager::removeFromScriptEngines() { | |
| 523 | + Q_ASSERT(_scriptEngines); | |
| 524 | + _scriptEngines.toStrongRef()->removeScriptEngine(shared_from_this()); | |
| 525 | +} | |
| 526 | + | |
| 513 | 527 | QString ScriptManager::getFilename() const { |
| 514 | 528 | QStringList fileNameParts = _fileNameString.split("/"); |
| 515 | 529 | QString lastPart; |
| @@ -987,6 +1001,7 @@ void ScriptManager::run() { · 471 unmodified lines | ||
| 987 | 1001 | |
| 988 | 1002 | PROFILE_RANGE(script, "ScriptMainLoop"); |
| 989 | 1003 | |
| 1004 | +//#define SCRIPT_DELAY_DEBUG | |
| 990 | 1005 | #ifdef SCRIPT_DELAY_DEBUG |
| 991 | 1006 | { |
| 992 | 1007 | auto actuallySleptUntil = clock::now(); |
| @@ -1066,6 +1081,13 @@ void ScriptManager::run() { · 73 unmodified lines | ||
| 1066 | 1081 | _isRunning = false; |
| 1067 | 1082 | emit runningStateChanged(); |
| 1068 | 1083 | emit doneRunning(); |
| 1084 | + _engine->disconnectSignalProxies(); | |
| 1085 | + // Process all remaining events | |
| 1086 | + { | |
| 1087 | + QEventLoop loop; | |
| 1088 | + loop.processEvents(); | |
| 1089 | + } | |
| 1090 | + _isDoneRunning = true; | |
| 1069 | 1091 | } |
| 1070 | 1092 | |
| 1071 | 1093 | // NOTE: This is private because it must be called on the same thread that created the timers, which is why |
| @@ -1123,6 +1145,7 @@ void ScriptManager::timerFired() { · 51 unmodified lines | ||
| 1123 | 1145 | return; // bail early |
| 1124 | 1146 | } |
| 1125 | 1147 | |
| 1148 | +//#define SCRIPT_TIMER_PERFORMANCE_STATISTICS | |
| 1126 | 1149 | #ifdef SCRIPT_TIMER_PERFORMANCE_STATISTICS |
| 1127 | 1150 | _timerCallCounter++; |
| 1128 | 1151 | if (_timerCallCounter % 100 == 0) { |