fix: await wl-copy exit code and fall through to xclip on failure (#7009)

The /copy command always set copied=true after spawning wl-copy without
awaiting its exit code. When wl-copy fails (e.g. in a sandboxed
environment that inherits WAYLAND_DISPLAY but not the socket), the
xclip/OSC 52 fallbacks never ran because copied was already true.

Fix: await the wl-copy spawn exit code and only claim success on exit
code 0. On failure, fall through to the x11 clipboard fallback.

Fixes #6872.
This commit is contained in:
Shakti 2026-07-24 10:28:37 +05:30 • committed by GitHub
parent 24bace27cf
commit 2d3f555429
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -104,15 +104,25 @@ export async function copyToClipboard(text: string): Promise<void> {
try {
// Verify wl-copy exists (spawn errors are async and won't be caught)
execSync("which wl-copy", { stdio: "ignore" });
// wl-copy with execSync hangs due to fork behavior; use spawn instead
const proc = spawn("wl-copy", [], { stdio: ["pipe", "ignore", "ignore"] });
proc.stdin.on("error", () => {
// Ignore EPIPE errors if wl-copy exits early
// wl-copy with execSync hangs due to fork behavior; use spawn instead.
// Await the exit code and only claim success on a clean exit, so a
// failed wl-copy falls through to the xclip/OSC 52 fallbacks.
const wlCopyExit = await new Promise<number>((resolve) => {
const proc = spawn("wl-copy", [], { stdio: ["pipe", "ignore", "ignore"] });
proc.on("error", () => resolve(1));
proc.on("close", (code) => resolve(code ?? 1));
proc.stdin.on("error", () => {
// Ignore EPIPE errors if wl-copy exits early
});
proc.stdin.write(text);
proc.stdin.end();
});
proc.stdin.write(text);
proc.stdin.end();
proc.unref();
copied = true;
if (wlCopyExit === 0) {
copied = true;
} else if (hasX11Display) {
copyToX11Clipboard(options);
copied = true;
}
} catch {
if (hasX11Display) {
copyToX11Clipboard(options);