https://bugs.kde.org/show_bug.cgi?id=520260
Max Quinn <[email protected]> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |[email protected] --- Comment #4 from Max Quinn <[email protected]> --- I was running into this issue and after I failed to find anything myself I had Claude try to fix it. This report was written by Claude. I am sorry to whoever is reading through this and I am very sorry if it turns out to be useless but I do not have quite the level of technical knowledge to be able to fix this myself. I will try my best to answer any questions or provide any more information, but honestly I can't promise that I'll be of much help. Best of luck and thank you to whatever volunteer is going through this. I think I have the mechanism for this. Short version: the RDPGFX in-flight frame window is drained only by client frame acknowledgements and has no timeout, so a client that stops acknowledging wedges the video stream permanently while input keeps working. Environment krdp 6.7.4, FreeRDP 3.31.0, Fedora 44 (Nobara), kernel 7.2.8 Plasma 6.7.4 Wayland Client: Microsoft "Windows App" for Android, running on ChromeOS [app version: 11.0.26071.13915] [ChromeOS version: 154.0.8037.96] Host GPUs: NVIDIA RTX 3050 + AMD Granite Ridge iGPU, one monitor on each Symptom Connection succeeds, the first frame renders correctly, then video never updates again. Input continues to work for the whole "frozen" period -- typing and clicks land on the host and are visible on the physical monitors. Disconnect/reconnect gives one fresh frame, then freezes again. This is not GPU- or DMA-BUF-related Worth stating because this thread has been looking at Intel/Arc specifics and "Failed to create surface from DRM object". I reproduced the freeze identically with --virtual-monitor 1920x1080@1, i.e. a single output, a small surface, and no multi-GPU involvement. Same freeze, same timing. Whatever the DRM/encoder errors other reporters are seeing, the freeze itself reproduces without them. Measurements taken during a live frozen session Capture side is healthy: - both PipeWire nodes 'running', and the link between them 'active' - injecting pointer motion through the portal delivered ~40 frames on the capture node - an injected rubber-band drag produced real content damage, not just cursor movement Send side is completely idle: - ss -ti on the RDP socket: bytes_sent frozen at 9911521 across 8s and 12s samples (full-desktop config), and at 2633169 across 5s and across the whole drag test (virtual-monitor config) - zero bytes. KRdp is not sending anything at all, not sending corrupt or undecodable frames. So frames are arriving from KWin and nothing is leaving for the client. Suppress Output is ruled out: that path goes through setActive(false), which would deactivate the PipeWire stream. The stream stayed active throughout. Where it blocks (line numbers from Plasma/6.7) VideoStream.cpp:40 constexpr qsizetype MaximumInFlightFrames = 2; VideoStream.cpp:795 hasInFlightCapacity() -> pendingFrames.size() < 2 VideoStream.cpp:356 submission thread's first gate is !hasInFlightCapacity() VideoStream.cpp:845 pendingFrames.insert(frameId) on send VideoStream.cpp:635 pendingFrames.erase(itr) in onFrameAcknowledge() pendingFrames is erased in exactly one place: onFrameAcknowledge(). The only other things that touch it are clear() on an encoding-mode switch (:396) and on GFX channel re-advertisement (:531). There is no timeout anywhere. Once two frames are outstanding and unacknowledged, the submission thread spins on a 1ms sleep forever and the stream is dead for the life of the connection. Input is unaffected because it travels an entirely separate path through the portal, which is exactly why this presents as a client/input bug and why there are several open reports describing "black screen but input works" (see below). This client negotiates RDPGFX_CAPS_FLAG_AVC_DISABLED (0x20), so onCapsAdvertise() selects EncodingMode::Progressive. In that mode queueFrame() keeps only the newest frame and accumulates damage into it, so there is no memory growth -- it just silently stops sending. Still present in master master makes the window RTT-adaptive (maxInFlight recomputed in updateInFlightWindow() on rttChanged) but MaximumInFlightFrames = 2 is now the *floor*, the drain is still acknowledgement-only, and the submission loop is byte-for-byte equivalent. Updating will not fix this. The one existing recovery path onCapsAdvertise() clears pendingFrames when a client re-advertises caps (treated as a GFX channel reset). mstsc does this; it may be why desktop Windows clients mostly recover. This Android client does not appear to, so there is no escape. What I have NOT confirmed That the client actually stops sending RDPGFX_FRAME_ACKNOWLEDGE. I inferred it: the pipeline demonstrably worked once (first frame rendered), capture stayed healthy, zero bytes left the socke in-flight window is the only non-recoverable gate on that path. I did not capture the wire or run an instrumented build. Confirmin cheap -- a qCDebug of frameId in onFrameAcknowledge() plus pendingFrames.size() in the submission loop would settle it connection. Happy to run that if someone points me at a build. Suggested fix Store a send timestamp alongside each pending frame id. If t outstanding frame exceeds some bound (a few seconds, or N * RTT from NetworkDetection), drop it from pendingFrames, warn once, an fresh full-damage frame. That turns a permanent freeze into a brief stutter and costs nothing for well-behaved clients. A strict would also recreate the surface / send RDPGFX_RESET_GRAPHICS. Possibly the same root cause Bug 525818 -- freeze on client minimise/lock, input still ac Same signature, different trigger. Bug 494715 -- black screen, keyboard and mouse still registe server device. Bug 507949 -- OOM when a client stops receiving data. In H26 queueFrame() appends unbounded and only clears on a keyframe, so a stuck in-flight window would grow without limit. Plausibly this defect with a different consequence depending on encoding mode. Unrelated minor thing noticed while reading logs: capVersionTo no cases for RDPGFX_CAPVERSION_105/106/107, so modern clients log "Selected caps: UNKNOWN_VERSION", which is misleading when debugging. -- You are receiving this mail because: You are watching all bug changes.
