jlcodes99/cockpit-tools · warning · std::io::Error
Interrupted
Interrupted
Error message
系统正在关闭,已取消启动 {} What it means
acquire_process_spawn_guard serializes process spawning across the app and refuses to hand out a spawn guard once application shutdown has begun (a shutdown flag checked via process_spawn_allowed/is_shutdown_started). It returns an io::Error of kind Interrupted carrying the cancelled program name. This prevents child processes from being launched while the app is tearing down.
Source
Thrown at src-tauri/src/modules/app_lifecycle.rs:36
pub fn is_shutdown_started() -> bool {
SHUTDOWN_STARTED.load(Ordering::SeqCst)
}
pub fn begin_shutdown() -> bool {
let _spawn_guard = lock_process_spawn();
!SHUTDOWN_STARTED.swap(true, Ordering::SeqCst)
}
#[cfg(target_os = "windows")]
fn cancel_system_shutdown() {
let _spawn_guard = lock_process_spawn();
SHUTDOWN_STARTED.store(false, Ordering::SeqCst);
}
pub fn acquire_process_spawn_guard(program: &str) -> std::io::Result<ProcessSpawnGuard> {
let guard = lock_process_spawn();
if !process_spawn_allowed(is_shutdown_started()) {
return Err(Error::new(
ErrorKind::Interrupted,
format!("系统正在关闭,已取消启动 {}", program),
));
}
Ok(ProcessSpawnGuard { _guard: guard })
}
#[cfg(target_os = "windows")]
pub fn install_system_shutdown_listener() -> Result<(), String> {
use std::sync::mpsc::sync_channel;
let (shutdown_tx, shutdown_rx) = sync_channel::<()>(1);
std::thread::Builder::new()
.name("cockpit-system-shutdown-cleanup".to_string())
.spawn(move || {
if shutdown_rx.recv().is_ok() {
crate::modules::logger::log_info(
"[Lifecycle] Windows 正在关闭,停止后台注入并禁止创建新子进程",View on GitHub (pinned to 1ed8b77992)
Solutions
- Treat this error as an expected cancellation: stop the operation and do not retry while shutdown is in progress.
- Check the shutdown-started flag before initiating any process launch, and subscribe to the shutdown signal to cancel pending launches.
- If the spawn must complete, restructure so the launch happens before shutdown begins, or persist the work and resume on next startup.
- If this occurs during normal operation (not shutdown), verify no code path incorrectly sets the shutdown flag early.
Example fix
// before
let guard = acquire_process_spawn_guard("powershell")?;
run_probe(guard);
// after
if is_shutdown_started() {
return Ok(()); // skip probe during shutdown
}
let guard = match acquire_process_spawn_guard("powershell") {
Ok(g) => g,
Err(e) if e.kind() == std::io::ErrorKind::Interrupted => return Ok(()),
Err(e) => return Err(e),
};
run_probe(guard); Defensive patterns
Strategy: fallback
Validate before calling
if is_shutdown_started() {
// skip launching; app is shutting down
return Ok(());
} Try / catch
match acquire_process_spawn_guard("prog") {
Err(e) if e.kind() == std::io::ErrorKind::Interrupted => Ok(()), // cancelled by shutdown
other => other,
} Prevention
- Check the shutdown flag before queueing any process launch
- Use a cancellation token shared with the shutdown signal for background tasks
- Persist pending work and resume after restart instead of spawning during teardown
- Treat ErrorKind::Interrupted from spawn guards as expected, not fatal
When it happens
Trigger: Calling acquire_process_spawn_guard (directly or via any code path that launches a child process) after SHUTDOWN_STARTED has been set — e.g. a background task or async job still trying to spawn PowerShell/other programs while the Tauri app is exiting.
Common situations: Background workers, timers, or queued tasks that outlive the shutdown signal and race with app close; long-running operations initiated just before the user quits the application.
Related errors
AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05).
Data as JSON: /api/errors/be1ed5255debaa9e.
Report an issue: GitHub.