summaryrefslogtreecommitdiff
path: root/indra/newview/llappviewer.cpp
diff options
context:
space:
mode:
authorAndrew Meadows <leviathan@lindenlab.com>2026-05-27 10:18:29 -0700
committerGitHub <noreply@github.com>2026-05-27 10:18:29 -0700
commita1b68fb8ed6c2589dd13bd9ba1fab7050ba38226 (patch)
tree0a86659664208322ac0953e17470133541c91b10 /indra/newview/llappviewer.cpp
parentf99e2233a40e3a7b88e6c54aa89a1bc0bcd76456 (diff)
Drop fewer packets on UDP packet flood (#5565)
* ACK received-but-unprocessed packets when queued * Prioritize packets between high- and low-priority (high-priority are: reliable packets that need an ACK) * Increase max size of LLPacketRing buffer
Diffstat (limited to 'indra/newview/llappviewer.cpp')
-rw-r--r--indra/newview/llappviewer.cpp79
1 files changed, 35 insertions, 44 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 79752d2315..7f06f991b0 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -5894,7 +5894,6 @@ void LLAppViewer::idleNetwork()
pingMainloopTimeout("idleNetwork");
gObjectList.mNumNewObjects = 0;
- S32 total_decoded = 0;
static LLCachedControl<bool> speed_test(gSavedSettings, "SpeedTest", false);
if (!speed_test())
@@ -5902,64 +5901,56 @@ void LLAppViewer::idleNetwork()
LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("idle network"); //LL_RECORD_BLOCK_TIME(FTM_IDLE_NETWORK); // decode
LLTimer check_message_timer;
- // Read all available packets from network
const S64 frame_count = gFrameCount; // U32->S64
- F32 total_time = 0.0f;
+ S32 total_decoded = 0;
+ // Process packets from network
+ LockMessageChecker lmc(gMessageSystem);
+ while (lmc.checkAllMessages(frame_count, gServicePump))
{
- bool needs_drain = false;
- LockMessageChecker lmc(gMessageSystem);
- while (lmc.checkAllMessages(frame_count, gServicePump))
- {
- if (gDoDisconnect)
- {
- // We're disconnecting, don't process any more messages from the server
- // We're usually disconnecting due to either network corruption or a
- // server going down, so this is OK.
- break;
- }
-
- total_decoded++;
+ ++total_decoded;
- if (total_decoded > MESSAGE_MAX_PER_FRAME)
+ // Time-box processing of network packets to prevent framerate catastrophe
+ if (check_message_timer.getElapsedTimeF32() >= CheckMessagesMaxTime)
+ {
+ // Drain the socket buffer so we know how many messages remain to process
+ S32 num_buffered_packets = gMessageSystem->drainUdpSocket();
+ if (num_buffered_packets > total_decoded)
{
- needs_drain = true;
- break;
+ // Grow CheckMessagesMaxTime until we process more packets each frame than arrive.
+ // This might spiral out of control on very slow computers on fast networks when
+ // the bandwidth settings are too high. There is a mechanism for providing backpressure
+ // to network bandwidth but it may be inadequate for the task
+ // (see LLViewerThrottle::updateDynamicThrottle() for more details).
+ CheckMessagesMaxTime *= 1.035f; // 3.5% ~= 2x in 20 frames, ~8x in 60 frames
}
-
- // Prevent slow packets from completely destroying the frame rate.
- // This usually happens due to clumps of avatars taking huge amount
- // of network processing time (which needs to be fixed, but this is
- // a good limit anyway).
- total_time = check_message_timer.getElapsedTimeF32();
- if (total_time >= CheckMessagesMaxTime)
+ else if (num_buffered_packets == 0)
{
- needs_drain = true;
- break;
+ // Reset CheckMessagesMaxTime to default value
+ CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
}
+ break;
}
- if (needs_drain || gMessageSystem->mPacketRing.getNumBufferedPackets() > 0)
+
+ if (total_decoded > MESSAGE_MAX_PER_FRAME)
{
- // Rather than allow packets to silently backup on the socket
- // we drain them into our own buffer so we know how many exist.
- S32 num_buffered_packets = gMessageSystem->drainUdpSocket();
- if (num_buffered_packets > 0)
- {
- // Increase CheckMessagesMaxTime so that we will eventually catch up
- CheckMessagesMaxTime *= 1.035f; // 3.5% ~= 2x in 20 frames, ~8x in 60 frames
- }
+ // MESSAGE_MAX_PER_FRAME is very high (400)
+ // We expect to run out of time before reaching here, but just in case...
+ gMessageSystem->drainUdpSocket();
+ break;
}
- else
+
+ if (gDoDisconnect)
{
- // Reset CheckMessagesMaxTime to default value
- CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
+ // We're disconnecting so no need to process packets.
+ break;
}
+ }
- // Handle per-frame message system processing.
+ // Handle per-frame message system processing.
- static LLCachedControl<F32> ack_collection_time(gSavedSettings, "AckCollectTime", 0.1f);
- lmc.processAcks(ack_collection_time());
- }
+ static LLCachedControl<F32> ack_collection_time(gSavedSettings, "AckCollectTime", 0.1f);
+ lmc.processAcks(ack_collection_time());
}
add(LLStatViewer::NUM_NEW_OBJECTS, gObjectList.mNumNewObjects);