Skip to content

Commit 459bd1e

Browse files
Merge branch 'release/2026.01' into project/voice_moderation
2 parents c5c9b1f + b4a6af5 commit 459bd1e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+699
-268
lines changed

indra/llcommon/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ set(llcommon_SOURCE_FILES
101101
lluri.cpp
102102
lluriparser.cpp
103103
lluuid.cpp
104+
llwatchdog.cpp
104105
llworkerthread.cpp
105106
hbxxh.cpp
106107
u64.cpp
@@ -240,6 +241,7 @@ set(llcommon_HEADER_FILES
240241
lluri.h
241242
lluriparser.h
242243
lluuid.h
244+
llwatchdog.h
243245
llwin32headers.h
244246
llworkerthread.h
245247
hbxxh.h

indra/llcommon/lleventcoro.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,18 @@ void llcoro::suspendUntilTimeout(float seconds)
137137
suspendUntilEventOnWithTimeout(bogus, seconds, timedout);
138138
}
139139

140+
void llcoro::suspendUntilNextFrame()
141+
{
142+
LLCoros::checkStop();
143+
LLCoros::TempStatus st("waiting for next frame");
144+
145+
// Listen for the next event on the "mainloop" event pump.
146+
// Once per frame we get mainloop.post(newFrame);
147+
LLEventPumpOrPumpName mainloop_pump("mainloop");
148+
// Wait for the next event (the event data is ignored).
149+
suspendUntilEventOn(mainloop_pump);
150+
}
151+
140152
namespace
141153
{
142154

indra/llcommon/lleventcoro.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ void suspend();
8484
*/
8585
void suspendUntilTimeout(float seconds);
8686

87+
/**
88+
* Yield control from a coroutine until the next mainloop's newFrame event.
89+
*/
90+
void suspendUntilNextFrame();
91+
8792
/**
8893
* Post specified LLSD event on the specified LLEventPump, then suspend for a
8994
* response on specified other LLEventPump. This is more than mere

indra/llcommon/llthread.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,11 @@ void LLThread::tryRun()
240240
LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
241241
main_queue->post(
242242
// Bind the current exception, rethrow it in main loop.
243-
[exc = std::current_exception()]() { std::rethrow_exception(exc); });
243+
[exc = std::current_exception(), name = mName]()
244+
{
245+
LL_INFOS("THREAD") << "Rethrowing exception from thread " << name << LL_ENDL;
246+
std::rethrow_exception(exc);
247+
});
244248
}
245249
#endif // else LL_WINDOWS
246250
}
Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@
2424
* $/LicenseInfo$
2525
*/
2626

27+
// Precompiled header
28+
#include "linden_common.h"
2729

28-
#include "llviewerprecompiledheaders.h"
2930
#include "llwatchdog.h"
3031
#include "llthread.h"
31-
#include "llappviewer.h"
3232

3333
constexpr U32 WATCHDOG_SLEEP_TIME_USEC = 1000000U;
3434

@@ -67,7 +67,9 @@ class LLWatchdogTimerThread : public LLThread
6767
};
6868

6969
// LLWatchdogEntry
70-
LLWatchdogEntry::LLWatchdogEntry()
70+
LLWatchdogEntry::LLWatchdogEntry(const std::string& thread_name)
71+
: mThreadName(thread_name)
72+
, mThreadID(LLThread::currentID())
7173
{
7274
}
7375

@@ -89,11 +91,16 @@ void LLWatchdogEntry::stop()
8991
LLWatchdog::getInstance()->remove(this);
9092
}
9193
}
94+
std::string LLWatchdogEntry::getThreadName() const
95+
{
96+
return mThreadName + llformat(": %d", mThreadID);
97+
}
9298

9399
// LLWatchdogTimeout
94100
const std::string UNINIT_STRING = "uninitialized";
95101

96-
LLWatchdogTimeout::LLWatchdogTimeout() :
102+
LLWatchdogTimeout::LLWatchdogTimeout(const std::string& thread_name) :
103+
LLWatchdogEntry(thread_name),
97104
mTimeout(0.0f),
98105
mPingState(UNINIT_STRING)
99106
{
@@ -175,7 +182,7 @@ void LLWatchdog::remove(LLWatchdogEntry* e)
175182
unlockThread();
176183
}
177184

178-
void LLWatchdog::init()
185+
void LLWatchdog::init(func_t set_error_state_callback)
179186
{
180187
if (!mSuspectsAccessMutex && !mTimer)
181188
{
@@ -188,6 +195,7 @@ void LLWatchdog::init()
188195
// start needs to use the mSuspectsAccessMutex
189196
mTimer->start();
190197
}
198+
mCreateMarkerFnc = set_error_state_callback;
191199
}
192200

193201
void LLWatchdog::cleanup()
@@ -241,17 +249,23 @@ void LLWatchdog::run()
241249
{
242250
mTimer->stop();
243251
}
244-
if (LLAppViewer::instance()->logoutRequestSent())
252+
253+
// Sets error marker file
254+
mCreateMarkerFnc();
255+
// Todo1: Warn user?
256+
// Todo2: We probably want to report even if 5 seconds passed, just not error 'yet'.
257+
std::string last_state = (*result)->getLastState();
258+
if (last_state.empty())
245259
{
246-
LLAppViewer::instance()->createErrorMarker(LAST_EXEC_LOGOUT_FROZE);
260+
LL_ERRS() << "Watchdog timer for thread " << (*result)->getThreadName()
261+
<< " expired; assuming viewer is hung and crashing" << LL_ENDL;
247262
}
248263
else
249264
{
250-
LLAppViewer::instance()->createErrorMarker(LAST_EXEC_FROZE);
265+
LL_ERRS() << "Watchdog timer for thread " << (*result)->getThreadName()
266+
<< " expired with state: " << last_state
267+
<< "; assuming viewer is hung and crashing" << LL_ENDL;
251268
}
252-
// Todo1: warn user?
253-
// Todo2: We probably want to report even if 5 seconds passed, just not error 'yet'.
254-
LL_ERRS() << "Watchdog timer expired; assuming viewer is hung and crashing" << LL_ENDL;
255269
}
256270
}
257271

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,17 @@
3030
#ifndef LL_TIMER_H
3131
#include "lltimer.h"
3232
#endif
33+
#include "llmutex.h"
34+
#include "llsingleton.h"
35+
36+
#include <functional>
3337

3438
// LLWatchdogEntry is the interface used by the tasks that
3539
// need to be watched.
3640
class LLWatchdogEntry
3741
{
3842
public:
39-
LLWatchdogEntry();
43+
LLWatchdogEntry(const std::string &thread_name);
4044
virtual ~LLWatchdogEntry();
4145

4246
// isAlive is accessed by the watchdog thread.
@@ -46,12 +50,19 @@ class LLWatchdogEntry
4650
virtual void reset() = 0;
4751
virtual void start();
4852
virtual void stop();
53+
virtual std::string getLastState() const { return std::string(); }
54+
typedef std::thread::id id_t;
55+
std::string getThreadName() const;
56+
57+
private:
58+
id_t mThreadID; // ID of the thread being watched
59+
std::string mThreadName;
4960
};
5061

5162
class LLWatchdogTimeout : public LLWatchdogEntry
5263
{
5364
public:
54-
LLWatchdogTimeout();
65+
LLWatchdogTimeout(const std::string& thread_name);
5566
virtual ~LLWatchdogTimeout();
5667

5768
bool isAlive() const override;
@@ -63,6 +74,7 @@ class LLWatchdogTimeout : public LLWatchdogEntry
6374
void setTimeout(F32 d);
6475
void ping(std::string_view state);
6576
const std::string& getState() {return mPingState; }
77+
std::string getLastState() const override { return mPingState; }
6678

6779
private:
6880
LLTimer mTimer;
@@ -81,10 +93,12 @@ class LLWatchdog : public LLSingleton<LLWatchdog>
8193
void add(LLWatchdogEntry* e);
8294
void remove(LLWatchdogEntry* e);
8395

84-
void init();
96+
typedef std::function<void()> func_t;
97+
void init(func_t set_error_state_callback);
8598
void run();
8699
void cleanup();
87100

101+
88102
private:
89103
void lockThread();
90104
void unlockThread();
@@ -94,6 +108,11 @@ class LLWatchdog : public LLSingleton<LLWatchdog>
94108
LLMutex* mSuspectsAccessMutex;
95109
LLWatchdogTimerThread* mTimer;
96110
U64 mLastClockCount;
111+
112+
// At the moment watchdog expects app to set markers in mCreateMarkerFnc,
113+
// but technically can be used to set any error states or do some cleanup
114+
// or show warnings.
115+
func_t mCreateMarkerFnc;
97116
};
98117

99118
#endif // LL_LLTHREADWATCHDOG_H

indra/llcommon/workqueue.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,15 @@ void LL::WorkQueueBase::callWork(const Work& work)
216216
LL_WARNS("LLCoros") << "Capturing and rethrowing uncaught exception in WorkQueueBase "
217217
<< getKey() << LL_ENDL;
218218

219+
std::string name = getKey();
219220
LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
220221
main_queue->post(
221222
// Bind the current exception, rethrow it in main loop.
222-
[exc = std::current_exception()]() { std::rethrow_exception(exc); });
223+
[exc = std::current_exception(), name]()
224+
{
225+
LL_INFOS("LLCoros") << "Rethrowing exception from WorkQueueBase::callWork " << name << LL_ENDL;
226+
std::rethrow_exception(exc);
227+
});
223228
}
224229
else
225230
{

indra/llcommon/workqueue.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,11 @@ namespace LL
530530
reply,
531531
// Bind the current exception to transport back to the
532532
// originating WorkQueue. Once there, rethrow it.
533-
[exc = std::current_exception()](){ std::rethrow_exception(exc); });
533+
[exc = std::current_exception()]()
534+
{
535+
LL_INFOS("LLCoros") << "Rethrowing exception from WorkQueueBase::postTo" << LL_ENDL;
536+
std::rethrow_exception(exc);
537+
});
534538
}
535539
},
536540
// if caller passed a TimePoint, pass it along to post()

indra/llimage/llimage.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -709,8 +709,20 @@ U8* LLImageBase::allocateData(S32 size)
709709
mData = (U8*)ll_aligned_malloc_16(size);
710710
if (!mData)
711711
{
712-
LL_WARNS() << "Failed to allocate image data size [" << size << "]" << LL_ENDL;
713-
mBadBufferAllocation = true;
712+
constexpr S32 MAX_TOLERANCE = 1024 * 1024 * 4; // 4 MB
713+
if (size > MAX_TOLERANCE)
714+
{
715+
// If a big image failed to allocate, tollerate it for now.
716+
// It's insightfull when crash logs without obvious cause are being analyzed,
717+
// so a crash in a random location that normally is a mystery can get proper handling.
718+
LL_WARNS() << "Failed to allocate image data size [" << size << "]" << LL_ENDL;
719+
}
720+
else
721+
{
722+
// We are too far gone if we can't allocate a small buffer.
723+
LLError::LLUserWarningMsg::showOutOfMemory();
724+
LL_ERRS() << "Failed to allocate image data size [" << size << "]" << LL_ENDL;
725+
}
714726
}
715727
}
716728

indra/llmessage/llassetstorage.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,9 @@ const char* LLAssetStorage::getErrorString(S32 status)
13161316
case LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE:
13171317
return "Asset request: asset not found in database";
13181318

1319+
case LL_ERR_NO_CAP:
1320+
return "Asset request: region or asset capability not available";
1321+
13191322
case LL_ERR_EOF:
13201323
return "End of file";
13211324

0 commit comments

Comments
 (0)