fix(server): keep newest queued waves on per-batch overflow#1276
Open
clintcan wants to merge 1 commit into
Open
fix(server): keep newest queued waves on per-batch overflow#1276clintcan wants to merge 1 commit into
clintcan wants to merge 1 commit into
Conversation
`dispatch_server_events` previously kept the oldest 4 queued `RdpsndServerMessage::Wave` events per batch and dropped any beyond that. Since `events.drain(..)` iterates oldest-first and `wave_limit` counts down from 4, the first 4 waves in the batch were always the ones sent — i.e. the *oldest* are kept, the *newest* are dropped. That means a one-time dispatch stall (e.g. a video encode holding the server lock) bakes itself in as a permanent audio offset: the client plays the stale 4 waves and the fresh ones are gone. The intent was clearly the opposite — bound latency by discarding stale audio in favor of recent audio. Compute the wave count up front and skip the leading `total - 4` waves instead. Same `WAVE_KEEP = 4` budget, just applied to the right end of the batch. No behavior change in steady state (when fewer than 4 waves are queued, no skip happens). Only the recovery path after a stall is fixed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
RdpServer::dispatch_server_eventsincrates/ironrdp-server/src/server.rskeeps the oldest 4 queuedRdpsndServerMessage::Waveevents per batch and drops the rest:events.drain(..)iterates oldest-first;wave_limitcounts down from 4. So the four waves that survive are always the four oldest in the batch, and any newer waves are dropped.This means a one-time dispatch stall — e.g. a video encode holding the server mutex for longer than the audio sample interval — bakes itself in as a permanent audio-latency offset: the client gets the 4 stale waves and the fresh ones it should be playing next are gone. The intent of the limit appears to be the opposite — bound latency by discarding stale audio in favor of recent audio.
I hit this building a macOS RDP server on top of
ironrdp-server: after any video-encode hiccup, audio playback would lag the source by hundreds of milliseconds and never recover.Fix
Count the wave events up front, compute how many leading ones to skip (
total - WAVE_KEEP), and skip those. SameWAVE_KEEP = 4budget — applied to the right end of the batch.Safety / scope
No behavior change in steady state. When fewer than
WAVE_KEEPwaves are queued (the common case — dispatch keeps up with capture),wave_skip == 0and every wave is sent, exactly as today.Only the recovery path after a stall changes. Instead of "keep the oldest 4, lose the rest" (permanent offset), it's now "skip the oldest, keep the newest 4" (transient gap, then back in sync).
One extra
events.iter().filter(...).count()per dispatch call. The dispatch is already proportional to batch size, so this is the same big-O.All comments and the
WAVE_KEEP = 4value are preserved; just retargeted.Verification
Built and tested in the [Devolutions/IronRDP] workspace:
End-to-end: my downstream project ran a vendored fork with exactly this patch through hundreds of mstsc / Microsoft Remote Desktop for Mac sessions during a long debugging cycle. Audio recovers cleanly from video-encode contention now; without the patch, latency grows monotonically across the session.