diff options
| author | Erik Kundiman <erik@megapahit.org> | 2026-03-30 17:10:44 +0800 |
|---|---|---|
| committer | Erik Kundiman <erik@megapahit.org> | 2026-03-30 17:10:44 +0800 |
| commit | 14239ba6f6d4a73038a270de5d8f295fb59498bd (patch) | |
| tree | b64cb90623d9cf4709fc2bec5a51b4c99a421a4a /indra/llcommon/llwatchdog.cpp | |
| parent | eac10375e294cd24c21c09497e838e70dcf4d74a (diff) | |
| parent | f148dbcc8a9566f1f717fdeb00813ad57427bee7 (diff) | |
Merge tag 'Second_Life_Release#f148dbcc-26.2' into 2026.02
Diffstat (limited to 'indra/llcommon/llwatchdog.cpp')
| -rw-r--r-- | indra/llcommon/llwatchdog.cpp | 70 |
1 files changed, 57 insertions, 13 deletions
diff --git a/indra/llcommon/llwatchdog.cpp b/indra/llcommon/llwatchdog.cpp index 1bc1283d0b..1622aeb180 100644 --- a/indra/llcommon/llwatchdog.cpp +++ b/indra/llcommon/llwatchdog.cpp @@ -87,7 +87,7 @@ void LLWatchdogEntry::start() void LLWatchdogEntry::stop() { // this can happen very late in the shutdown sequence - if (!LLWatchdog::wasDeleted()) + if (LLWatchdog::instanceExists()) { LLWatchdog::getInstance()->remove(this); } @@ -173,6 +173,17 @@ void LLWatchdog::add(LLWatchdogEntry* e) { lockThread(); mSuspects.insert(e); + + if (!mFrozeList.empty()) + { + mFrozeList.erase(e); + if (mFrozeList.empty()) + { + // Clear error marker file if there is no frozen threads, + // viewer is responsive again. + mClearMarkerFnc(); + } + } unlockThread(); } @@ -183,7 +194,12 @@ void LLWatchdog::remove(LLWatchdogEntry* e) unlockThread(); } -void LLWatchdog::init(func_t set_error_state_callback) +void LLWatchdog::init( + create_marker_func_t error_state_callback, + clear_marker_func_t clear_marker_callback, + report_func_t report_callback, + notify_func_t notify_callback, + bool crash_on_freeze) { if (!mSuspectsAccessMutex && !mTimer) { @@ -196,7 +212,11 @@ void LLWatchdog::init(func_t set_error_state_callback) // start needs to use the mSuspectsAccessMutex mTimer->start(); } - mCreateMarkerFnc = set_error_state_callback; + mCreateMarkerFnc = error_state_callback; + mClearMarkerFnc = clear_marker_callback; + mCrashReportFnc = report_callback; + mNotifyFnc = notify_callback; + mCrashOnFreeze = crash_on_freeze; } void LLWatchdog::cleanup() @@ -251,21 +271,45 @@ void LLWatchdog::run() mTimer->stop(); } - // Sets error marker file - mCreateMarkerFnc(); - // Todo1: Warn user? - // Todo2: We probably want to report even if 5 seconds passed, just not error 'yet'. std::string last_state = (*result)->getLastState(); - if (last_state.empty()) + std::string description = "Watchdog timer for thread " + (*result)->getThreadName() + " expired"; + if (!last_state.empty()) { - LL_ERRS() << "Watchdog timer for thread " << (*result)->getThreadName() - << " expired; assuming viewer is hung and crashing" << LL_ENDL; + description += " with state: " + last_state; + } + description += "; assuming viewer is hung and crashing"; + + if (!mCrashOnFreeze) + { + // Sets watchdog marker file + mCreateMarkerFnc(false); + // If it's mainloop and it somehow recovers, it will re-add itself + mSuspects.erase(*result); + mFrozeList.insert(*result); + LL_WARNS() << description << LL_ENDL; } else { - LL_ERRS() << "Watchdog timer for thread " << (*result)->getThreadName() - << " expired with state: " << last_state - << "; assuming viewer is hung and crashing" << LL_ENDL; + + if (!mCrashReportFnc(description)) + { + // Sets error marker file + mCreateMarkerFnc(true); + // If false is returned, then we failed to report the issue to bugsplat, + // instead, Notify user, then crash viewer. + // Todo: ask user if viewer should quit or wait? + mNotifyFnc(); + LL_ERRS() << description << LL_ENDL; + } + else + { + // Sets watchdog marker file + mCreateMarkerFnc(false); + // Already reported, don't report again. + // If it's mainloop and it somehow recovers, it will re-add itself + mSuspects.erase(result); + mFrozeList.insert(*result); + } } } } |
