{"record":{"id":"02ffa8369eb2c075","repo":"jlcodes99/cockpit-tools","slug":"timedout-02ffa8","errorCode":"TimedOut","errorMessage":"process timed out after {:?}","messagePattern":"process timed out after (.+?)","errorType":"error_code","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/src/modules/process_timeout.rs","lineNumber":50,"sourceCode":"        std::thread::spawn(move || {\n            let mut output = Vec::new();\n            pipe.read_to_end(&mut output).map(|_| output)\n        })\n    });\n    let deadline = Instant::now() + timeout;\n\n    let status = loop {\n        match child.try_wait() {\n            Ok(Some(status)) => break status,\n            Ok(None) => {\n                if Instant::now() >= deadline {\n                    let _ = child.kill();\n                    let _ = child.wait();\n                    // Do not join readers on the kill path: a surviving descendant may\n                    // still hold an inherited pipe, and the timeout path must stay bounded.\n                    drop(stdout_reader);\n                    drop(stderr_reader);\n                    return Err(io::Error::new(\n                        io::ErrorKind::TimedOut,\n                        format!(\"process timed out after {:?}\", timeout),\n                    ));\n                }\n                std::thread::sleep(Duration::from_millis(20));\n            }\n            Err(error) => {\n                let _ = child.kill();\n                let _ = child.wait();\n                drop(stdout_reader);\n                drop(stderr_reader);\n                return Err(error);\n            }\n        }\n    };\n\n    let stdout = join_reader_with_deadline(stdout_reader, deadline)?;\n    let stderr = join_reader_with_deadline(stderr_reader, deadline)?;","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src-tauri/src/modules/process_timeout.rs#L32-L68","documentation":"output_with_timeout runs a child process while polling for completion; when the process exceeds the given timeout it is killed, pipe readers are dropped without joining (a surviving descendant may hold the inherited pipe), and an io::Error of kind TimedOut with 'process timed out after {timeout:?}' is returned. It is the generic bounded command runner used by completes_fast_command and related helpers.","triggerScenarios":"Calling output_with_timeout (or completes_fast_command) with a command that runs longer than the supplied Duration — e.g. a hung child, infinite-running command, or timeout set too short.","commonSituations":"Probing whether a command 'completes fast' when the command actually hangs; network-bound CLIs stalling; timeout budget miscalibrated for slow machines.","solutions":["Raise the timeout Duration to fit the command's worst-case runtime.","Retry the command once with a larger budget if transient slowness is plausible.","Investigate why the child hangs (stdin waiting? network? prompt?) and fix the invocation (e.g. pipe stdin, add non-interactive flags).","Handle the TimedOut error explicitly and fall back to a default result instead of propagating."],"exampleFix":"// before\nlet out = output_with_timeout(&mut cmd, Duration::from_secs(3))?;\n\n// after\nmatch output_with_timeout(&mut cmd, Duration::from_secs(10)) {\n    Ok(out) => out,\n    Err(e) if e.kind() == std::io::ErrorKind::TimedOut => {\n        eprintln!(\"command exceeded 10s, using default\");\n        default_output()\n    }\n    Err(e) => return Err(e),\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match output_with_timeout(&mut cmd, timeout) {\n    Err(e) if e.kind() == std::io::ErrorKind::TimedOut => {\n        eprintln!(\"command exceeded {:?}; using fallback\", timeout);\n        fallback()\n    }\n    other => other,\n}","preventionTips":["Set timeouts above the command's realistic worst-case duration","Run commands non-interactively (pipe stdin, disable prompts) so they cannot hang waiting for input","Measure actual command latency and calibrate the timeout empirically","For network-bound commands, add their own connect/read timeouts so the outer kill is a last resort"],"tags":["timeout","process","io-error","rust"],"backgroundTag":"process-timeout","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}