fix(wayland): back off the polling display lookups after a failure (drm) (#15865)

* fix(wayland): back off the polling display lookups after a failure (drm)

In drm builds an enumeration that fails with no endpoint named in the
environment falls back to the socket probe, which forks a child bounded by
seconds, and the display service asks again every 300 ms -- at a greeter
with no reachable compositor that is a probe child per turn, forever. Such
a failure now stamps a shared 5 s backoff, and only the polling callers
honor it: the 300 ms displays-changed check skips its turn and the 1.5 s
live layout poll returns no answer for that turn.

Only the failure that would fork stamps. A session server is spawned with
WAYLAND_DISPLAY set, so its failed connect bails in-process before any
fork; stamping there would buy nothing and cost recovery latency, so live
sessions keep master's behavior exactly. The stamp also survives
clear_wayland_displays_cache: it describes the seat, not the cache, and
the ~1/s capturer rebuild loop clears on every teardown -- dropping the
stamp with the cache would let that loop defeat the backoff and would
turn every post-hotplug failure into a "first" one forever.

The displays-changed check weighs the backoff against what is already
published. With nothing synced yet it always populates -- an unaugmented
DRM list beats the empty broadcast the send path would otherwise emit.
With a synced layout, a suppressed turn keeps it, and a fresh first
failure keeps it too; only a failure that persists across a backoff
replaces it with the DRM stack, so a hotplug at a failing seat converges
within one backoff while a transient failure never tears down a good
layout.

One-shot callers -- session init, pipewire stream setup, capturer info --
keep probing fresh through get_displays, whose failure semantics are
unchanged: replaying a transient failure there would latch an empty answer
into session-long state. Non-drm builds compile none of this.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(wayland): log DRM lookup failure once

* fix(wayland): reset lookup warning after recovery

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
RustDesk
2026-08-18 09:57:06 +08:00
committed by GitHub
parent 14a4b197ad
commit 6a27910f34
2 changed files with 143 additions and 12 deletions

View File

@@ -346,8 +346,21 @@ fn check_get_displays_changed_msg() -> Option<Message> {
// list that overwrites the login peer-info displays and the client shows "No displays".
#[cfg(feature = "drm")]
if super::drm_capturer::is_available_cached() {
if let Some(displays) = super::drm_capturer::get_display_infos() {
SYNC_DISPLAYS.lock().unwrap().check_changed(&displays);
let synced = !SYNC_DISPLAYS.lock().unwrap().displays.is_empty();
let stamped_before = scrap::wayland::display::wayland_failure_stamped();
// With nothing published yet, even the unaugmented DRM list beats the empty
// broadcast below; with a synced layout, a suppressed turn keeps it instead.
if !synced || !scrap::wayland::display::wayland_lookup_suppressed() {
if let Some(displays) = super::drm_capturer::get_display_infos() {
// A first failure keeps the synced layout for one backoff; only a
// failure that persists across one replaces it with the DRM stack.
if !synced
|| stamped_before
|| !scrap::wayland::display::wayland_lookup_suppressed()
{
SYNC_DISPLAYS.lock().unwrap().check_changed(&displays);
}
}
}
}
return get_displays_msg();