Fix Wayland FD leak and clipboard sync feedback loop - #51
Open
halfcrazy wants to merge 2 commits into
Open
Conversation
halfcrazy
force-pushed
the
fix/wayland-fd-leak-and-sync-loop
branch
from
July 8, 2026 05:17
0d60c93 to
d8670c4
Compare
Reuse a persistent Wayland data-control connection in WlrBackend instead of opening a new wl-clipboard-rs session on every get/set, which caused EMFILE crashes under polling. Upgrade wl-clipboard-rs and wayland-client, and rewrite keep_synced to track per-clipboard state with a post-sync settle period so X11/Wayland write lag no longer spams sync logs. Fixes dnut#50 Co-authored-by: Cursor <cursoragent@cursor.com>
halfcrazy
force-pushed
the
fix/wayland-fd-leak-and-sync-loop
branch
from
July 28, 2026 02:38
d8670c4 to
ba5ebda
Compare
Large clipboard transfers exposed three failures that wiped or froze clipboard synchronization: - wlr_backend served data-source Send requests inline during event dispatch with a blocking write. Once the main loop owned the selection, its own get_text() roundtrip triggered Send for content larger than the pipe capacity: the write blocked waiting for the read end, which only runs after the roundtrip returns — a deadlock that froze all syncing and left Wayland pastes unserved until the watchdog restart. Send is now served from a side thread, and a failed write no longer destroys the source (a reader going away must not clear the clipboard). - X11 reads ran synchronously in the poll loop. Slow INCR transfers (selection owners proxying data from another machine) starved Wayland event dispatch, so Wayland apps timed out pasting. Reads now run in a dedicated watcher thread with a bounded timeout and populate a cache; the poll loop never blocks on X11. This also replaces the terminal-clipboard wrapper with direct x11-clipboard usage, lifting its hardcoded 2s read timeout that large transfers could never meet. - Transient backend read failures (Wayland NoSeats/NoMimeType when the selection holds non-text data, X11 errors collapsed by unwrap_or_default) surfaced as empty strings and were propagated as clipboard clears, wiping every synced clipboard. Empty reads are now never treated as changes.
Author
|
ping |
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.
Summary
WlrBackendwith a persistent Wayland data-control connection, mirroring the existingX11Backendpattern, so polling no longer opens a new wl-clipboard-rs session on everyget()/set()and exhausts file descriptors (EMFILE after ~5 minutes under GNOME Wayland).wl-clipboard-rsto 0.9.3 andwayland-clientto 0.31.14 (addsext-data-controlsupport on GNOME).keep_syncedto track per-clipboard last-known content and add a short post-sync settle period, preventing the X11/Wayland write-lag feedback loop that spammedclipboard updated from display :1logs.Fixes #50
Root cause
WlrClipboardcalledwl_clipboard_rs::paste::get_contents()/copy::Options::copy()on every poll (~5 Hz per clipboard). Each call runsinitialize()and opens a new Wayland socket, leaking FDs untilulimit -nis hit.Separately, after syncing a change, comparing all clipboards against
clipboards[0]caused repeated false positives when Wayland and X11 reads diverged briefly after a write.Test plan
WlrClipboard { wayland-1 }+X11Clipboard { :1 }:1spam)Made with Cursor