perl_subprocess_runtime/os_runtime/mod.rs
1//! OS-backed subprocess runtime.
2
3mod invocation;
4mod process;
5mod validation;
6#[cfg(windows)]
7mod windows;
8
9#[cfg(windows)]
10pub(crate) use invocation::resolve_command_invocation;
11use process::run_os_command;
12
13use crate::{SubprocessError, SubprocessOutput, SubprocessRuntime};
14
15#[cfg(windows)]
16pub(crate) use windows::{windows_program_priority, windows_quote_for_cmd};
17
18/// Default implementation using `std::process::Command`.
19pub struct OsSubprocessRuntime {
20 timeout_secs: Option<u64>,
21}
22
23impl OsSubprocessRuntime {
24 /// Create a new OS subprocess runtime with no timeout.
25 pub fn new() -> Self {
26 Self { timeout_secs: None }
27 }
28
29 /// Create a new OS subprocess runtime with the given wall-clock timeout.
30 ///
31 /// If the subprocess does not complete within `timeout_secs` seconds the
32 /// call returns a `SubprocessError` with a "timed out" message and attempts
33 /// to terminate the spawned process before returning.
34 ///
35 /// # Stdin size caveat
36 ///
37 /// Stdin data is written synchronously before the timeout poll loop begins.
38 /// If the subprocess hangs before consuming stdin and the data exceeds the
39 /// OS pipe buffer (~64 KiB on Linux), `run_command` will block in the write
40 /// phase and the timeout will not fire. For typical Perl source files this
41 /// is not a concern.
42 ///
43 /// # Panics
44 ///
45 /// Panics if `timeout_secs` is zero (a zero-second timeout would time out
46 /// every command immediately and is almost certainly a caller bug).
47 pub fn with_timeout(timeout_secs: u64) -> Self {
48 assert!(timeout_secs > 0, "timeout_secs must be greater than zero");
49 Self { timeout_secs: Some(timeout_secs) }
50 }
51}
52
53impl Default for OsSubprocessRuntime {
54 fn default() -> Self {
55 Self::new()
56 }
57}
58
59impl SubprocessRuntime for OsSubprocessRuntime {
60 fn run_command(
61 &self,
62 program: &str,
63 args: &[&str],
64 stdin: Option<&[u8]>,
65 ) -> Result<SubprocessOutput, SubprocessError> {
66 run_os_command(program, args, stdin, self.timeout_secs)
67 }
68}