mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-09 16:38:07 +00:00
Fix #5236: cap the wait for open -a at two seconds
A stalled `open -a` no longer holds the window: Edit Original waits at most two seconds for its exit status (enough to report an app it can't open), then leaves the launch running and reaps it on a thread of its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
committed by
bflatastic
co-authored by
Claude Opus 5.5
parent
7c5670b797
commit
79c8d1a7e0
@@ -357,18 +357,39 @@ fn open_file_with(app: &str, path: &str) -> Result<(), String> {
|
||||
c.arg(path);
|
||||
c
|
||||
};
|
||||
// macOS: `open` returns once Launch Services has the request, so waiting for it is brief and
|
||||
// reports an app it can't open (a folder named `.app` that isn't a bundle). Elsewhere the
|
||||
// editor itself runs: waiting would last until it closes.
|
||||
// macOS: `open` returns once Launch Services has the request, so a short wait reports an app
|
||||
// it can't open (a folder named `.app` that isn't a bundle). The wait is capped so a stalled
|
||||
// `open` never holds the window: past it, the launch is left to run. Elsewhere the editor
|
||||
// itself runs: waiting would last until it closes.
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let out = c.output().map_err(|e| format!("can't open {path} in {}: {e}", app.display()))?;
|
||||
if out.status.success() {
|
||||
return Ok(());
|
||||
const WAIT: std::time::Duration = std::time::Duration::from_secs(2);
|
||||
let fail = |why: String| format!("can't open {path} in {}: {why}", app.display());
|
||||
let mut child = c.stderr(std::process::Stdio::piped()).spawn().map_err(|e| fail(e.to_string()))?;
|
||||
let started = std::time::Instant::now();
|
||||
loop {
|
||||
match child.try_wait() {
|
||||
Ok(Some(status)) if status.success() => return Ok(()),
|
||||
Ok(Some(status)) => {
|
||||
let mut why = String::new();
|
||||
if let Some(mut err) = child.stderr.take() {
|
||||
// Best effort: without its message the exit status says why.
|
||||
let _ = std::io::Read::read_to_string(&mut err, &mut why);
|
||||
}
|
||||
let why = why.trim().to_string();
|
||||
return Err(fail(if why.is_empty() { status.to_string() } else { why }));
|
||||
}
|
||||
Ok(None) if started.elapsed() < WAIT => std::thread::sleep(std::time::Duration::from_millis(20)),
|
||||
Ok(None) => {
|
||||
// Reaped off the UI thread once it ends.
|
||||
std::thread::spawn(move || {
|
||||
let _ = child.wait();
|
||||
});
|
||||
return Ok(());
|
||||
}
|
||||
Err(e) => return Err(fail(e.to_string())),
|
||||
}
|
||||
}
|
||||
let why = String::from_utf8_lossy(&out.stderr).trim().to_string();
|
||||
let why = if why.is_empty() { out.status.to_string() } else { why };
|
||||
Err(format!("can't open {path} in {}: {why}", app.display()))
|
||||
}
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
c.spawn().map(|_| ()).map_err(|e| format!("can't open {path} in {}: {e}", app.display()))
|
||||
|
||||
Reference in New Issue
Block a user