From 9b3b662f5dc2c8bac93dd1429a6d7a166549c3f4 Mon Sep 17 00:00:00 2001 From: wjrichards Date: Thu, 29 Oct 2026 15:54:32 -0400 Subject: [PATCH] Linux clipboard: the read worker holds the window as long as its clipboard The worker's closure named loader.cb, and a closure moves only the fields it names, so the worker's window clone was dropped when TextClipboard::new returned. A worker held by an owner that never answers could then outlive the window. The closure now calls Loader::load, which moves the whole Loader. Co-Authored-By: Claude Opus 5.5 --- apps/vectorcraft/src/clipboard.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/vectorcraft/src/clipboard.rs b/apps/vectorcraft/src/clipboard.rs index 7a45f42e8..aafb42b9b 100644 --- a/apps/vectorcraft/src/clipboard.rs +++ b/apps/vectorcraft/src/clipboard.rs @@ -785,6 +785,12 @@ mod wayland { _window: Arc, } + impl Loader { + fn load(&self) -> Result { + self.cb.load().map_err(|e| e.to_string()) + } + } + impl TextClipboard { /// None when `window` isn't a Wayland window or the read worker can't start. #[allow(unsafe_code)] @@ -797,7 +803,9 @@ mod wayland { // makes its own event queue on the display and doesn't close it. let (cb, reader) = unsafe { (smithay_clipboard::Clipboard::new(display), smithay_clipboard::Clipboard::new(display)) }; let loader = Loader { cb: reader, _window: window.clone() }; - let loads = Loads::spawn(move || loader.cb.load().map_err(|e| e.to_string()))?; + // `loader.load()`, not `loader.cb.load()`: a closure moves only the fields it names, + // and the worker must hold the window as long as its clipboard. + let loads = Loads::spawn(move || loader.load())?; Some(Self { cb, loads, _window: window }) }