jlcodes99/cockpit-tools · warning · std::io::Error
TimedOut
TimedOut
Error message
PowerShell 进程探测超时({}ms) What it means
`powershell_output_with_timeout` spawns a PowerShell child process to enumerate application processes; if the child does not finish within the configured timeout, it is killed and an `std::io::Error` with `ErrorKind::TimedOut` and message "PowerShell 进程探测超时({N}ms)" is returned. Callers (`collect_*_process_entries_from_powershell` for Codex, Antigravity, CodeBuddy, WorkBuddy) then fail their process discovery step.
Source
Thrown at crates/cockpit-core/src/modules/process_core_discovery.rs:460
if let Some(mut out) = child.stdout.take() {
let _ = out.read_to_end(&mut stdout);
}
if let Some(mut err) = child.stderr.take() {
let _ = err.read_to_end(&mut stderr);
}
let result = Ok(std::process::Output {
status,
stdout,
stderr,
});
log_command_trace_result(&preview, &result, start.elapsed());
return result;
}
if start.elapsed() >= timeout {
let _ = child.kill();
let _ = child.wait();
let result = Err(Error::new(
ErrorKind::TimedOut,
format!("PowerShell 进程探测超时({}ms)", timeout.as_millis()),
));
log_command_trace_result(&preview, &result, start.elapsed());
return result;
}
thread::sleep(Duration::from_millis(100));
}
}
#[cfg(target_os = "windows")]
fn cmd_output(args: &[&str]) -> std::io::Result<std::process::Output> {
use std::os::windows::process::CommandExt;
let mut command = Command::new("cmd");
command.creation_flags(CREATE_NO_WINDOW).args(args);
let preview = format_command_preview(&command);View on GitHub (pinned to 1ed8b77992)
Solutions
- Retry the discovery call — a warm PowerShell usually completes well within the timeout on the second run.
- Increase the timeout constant passed to `powershell_output_with_timeout` (e.g. 3s → 10s).
- Launch PowerShell with `-NoProfile` to skip slow profile scripts.
- Reduce the query cost (narrow the WMI/CIM filter) so enumeration finishes faster.
Example fix
// before
let entries = collect_codex_process_entries_from_powershell()?;
// after
let entries = match collect_codex_process_entries_from_powershell() {
Ok(e) => e,
Err(e) if e.kind() == std::io::ErrorKind::TimedOut => {
log::warn!("process discovery timed out, retrying once");
collect_codex_process_entries_from_powershell().unwrap_or_default()
}
Err(e) => return Err(e),
}; Defensive patterns
Strategy: retry
Validate before calling
// best-effort pre-check (Windows)
// ensure powershell.exe resolves before the timed call
which::which("powershell").map_err(|_| std::io::Error::new(std::io::ErrorKind::NotFound, "powershell not on PATH"))? Type guard
fn is_probe_timeout(e: &std::io::Error) -> bool {
e.kind() == std::io::ErrorKind::TimedOut && e.to_string().contains("PowerShell 进程探测超时")
} Try / catch
match powershell_output_with_timeout(&mut child, timeout) {
Ok(out) => out,
Err(e) if e.kind() == std::io::ErrorKind::TimedOut => {
log::warn!("probe timed out; retrying with warm powershell");
retry_once_or_default()
}
Err(e) => return Err(e.into()),
} Prevention
- Spawn PowerShell with -NoProfile to avoid slow profile load.
- Warm up PowerShell once at app start so later probes are fast.
- Set a generous timeout (>= 5-10s) with a single retry.
- Degrade gracefully: return an empty process list instead of failing the whole discovery.
When it happens
Trigger: PowerShell startup or the process query takes longer than the timeout budget — cold PowerShell first-run (profile loading, .NET JIT), heavily loaded CPU, or a very large number of running processes making the WMI/CIM query slow.
Common situations: First invocation after boot on Windows when PowerShell is not warm; antivirus scanning powershell.exe on launch; slow machines with hundreds of processes; overly tight timeout constants.
Related errors
AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05).
Data as JSON: /api/errors/1939df0a792183dc.
Report an issue: GitHub.