aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2025-07-17 11:41:17 +0200
committerGitHub <noreply@github.com>2025-07-17 11:41:17 +0200
commit19c159175c12a06e3517882487caa2f834f29033 (patch)
tree6f23f02728658a2f98376a5a682b86bcd78d0c74
parentfix(panes): do not default to tiled pane (#4295) (diff)
downloadsl0ppij-19c159175c12a06e3517882487caa2f834f29033.tar.gz
sl0ppij-19c159175c12a06e3517882487caa2f834f29033.tar.xz
sl0ppij-19c159175c12a06e3517882487caa2f834f29033.zip
fix(clipboard): reap process of external command (#4298)
* fix(clipboard): reap process of external command * docs(changelog): add PR
-rw-r--r--CHANGELOG.md1
-rw-r--r--zellij-server/src/tab/copy_command.rs29
2 files changed, 29 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a206b782..bffe11a6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* fix: better command detection when serializing layouts for resurrection (https://github.com/zellij-org/zellij/pull/4287)
* fix: slow startup on very large caches (https://github.com/zellij-org/zellij/pull/4292)
* fix: don't show popups in the welcome screen (https://github.com/zellij-org/zellij/pull/4294)
+* fix: reap processes when using an external clipboard tool (https://github.com/zellij-org/zellij/pull/4298)
## [0.42.2] - 2025-04-15
* refactor(terminal): track scroll_region as tuple rather than Option (https://github.com/zellij-org/zellij/pull/4082)
diff --git a/zellij-server/src/tab/copy_command.rs b/zellij-server/src/tab/copy_command.rs
index f0a592ef..eead0bd7 100644
--- a/zellij-server/src/tab/copy_command.rs
+++ b/zellij-server/src/tab/copy_command.rs
@@ -18,17 +18,44 @@ impl CopyCommand {
}
}
pub fn set(&self, value: String) -> Result<()> {
- let process = Command::new(self.command.clone())
+ let mut process = Command::new(self.command.clone())
.args(self.args.clone())
.stdin(Stdio::piped())
.spawn()
.with_context(|| format!("couldn't spawn {}", self.command))?;
process
.stdin
+ .take()
.context("could not get stdin")?
.write_all(value.as_bytes())
.with_context(|| format!("couldn't write to {} stdin", self.command))?;
+ // reap process with a 1 second timeout
+ std::thread::spawn(move || {
+ let timeout = std::time::Duration::from_secs(1);
+ let start = std::time::Instant::now();
+
+ loop {
+ match process.try_wait() {
+ Ok(Some(_)) => {
+ return; // Process finished normally
+ },
+ Ok(None) => {
+ if start.elapsed() > timeout {
+ let _ = process.kill();
+ log::error!("Copy operation times out after 1 second");
+ return;
+ }
+ std::thread::sleep(std::time::Duration::from_millis(50));
+ },
+ Err(e) => {
+ log::error!("Clipboard failure: {}", e);
+ return;
+ },
+ }
+ }
+ });
+
Ok(())
}
}