summaryrefslogtreecommitdiff
path: root/indra/llcommon/llwatchdog.cpp
diff options
context:
space:
mode:
authorJonathan "Geenz" Goodman <geenz@geenzo.com>2026-05-20 11:43:36 -0400
committerJonathan "Geenz" Goodman <geenz@geenzo.com>2026-05-20 11:43:36 -0400
commit3f82abe033887ff690398381563100735e008df4 (patch)
tree6c6c6bebf982cda7b056156fb206378dbc443fe7 /indra/llcommon/llwatchdog.cpp
parent491b0b32c74e2186dd34f9be8513bb08d390dfe2 (diff)
parent6d4c4c029ce43aa413266135829cd2bc00001890 (diff)
Merge branch 'main' into geenz/26.2-to-26.3
Diffstat (limited to 'indra/llcommon/llwatchdog.cpp')
-rw-r--r--indra/llcommon/llwatchdog.cpp71
1 files changed, 59 insertions, 12 deletions
diff --git a/indra/llcommon/llwatchdog.cpp b/indra/llcommon/llwatchdog.cpp
index d3242a6c96..66b565c763 100644
--- a/indra/llcommon/llwatchdog.cpp
+++ b/indra/llcommon/llwatchdog.cpp
@@ -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();
}
@@ -180,10 +191,16 @@ void LLWatchdog::remove(LLWatchdogEntry* e)
{
lockThread();
mSuspects.erase(e);
+ mFrozeList.erase(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 +213,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 +272,47 @@ 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
+ LLWatchdogEntry* froze_entry = *result;
+ mSuspects.erase(result);
+ mFrozeList.insert(froze_entry);
+ 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
+ LLWatchdogEntry* froze_entry = *result;
+ mSuspects.erase(result);
+ mFrozeList.insert(froze_entry);
+ }
}
}
}