Skip to main content

rskit_process/
lib.rs

1//! Subprocess execution with explicit I/O modes, process-group isolation, and timeouts.
2//!
3//! This crate provides functionality to execute external processes with:
4//! - Timeout support with configurable grace period
5//! - SIGTERM → SIGKILL escalation for graceful shutdown
6//! - Process group isolation to ensure child processes are properly terminated
7//! - Explicit captured, observed, and inherited stdio modes
8//! - Environment variable control
9//! - Working directory configuration
10//!
11//! # I/O modes
12//!
13//! `ProcessIo::Captured` captures stdout and stderr separately through pipes.
14//! It is deterministic for non-interactive commands, but it is not a terminal
15//! and cannot guarantee exact ordering between stdout and stderr.
16//!
17//! `ProcessIo::Observed` also uses separate pipes and supports live raw-byte or
18//! line callbacks with optional capture. Line observers split deterministically
19//! on `\n`, `\r`, and `\r\n`; invalid UTF-8 is reported lossily.
20//!
21//! `ProcessIo::Inherited` gives the child the parent stdio handles. This is the
22//! right mode for normal terminal commands, but it does not provide structured
23//! output capture.
24//!
25//! # Example
26//!
27//! ```no_run
28//! use rskit_process::{ProcessConfig, ProcessSpec, run_with_cancel};
29//! use std::time::Duration;
30//! use tokio_util::sync::CancellationToken;
31//!
32//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
33//! let spec = ProcessSpec::new("echo")
34//!     .arg("hello")
35//!     .arg("world");
36//!
37//! let config = ProcessConfig::default().with_timeout(Some(Duration::from_secs(30)));
38//!
39//! let result = run_with_cancel(&spec, &config, CancellationToken::new()).await?;
40//! println!("stdout: {}", result.stdout);
41//! println!("exit code: {:?}", result.exit_code);
42//! # Ok(())
43//! # }
44//! ```
45
46#![warn(missing_docs)]
47
48mod command;
49mod persistent;
50mod process_group;
51mod result;
52mod runner;
53mod signal;
54mod sync;
55
56pub use command::{
57    ArgRedaction, CapturedIo, DEFAULT_MAX_OUTPUT_BYTES, EnvPolicy, InheritedIo, InputPolicy,
58    ObservedIo, OutputPolicy, ProcessConfig, ProcessIo, ProcessSpec, SignalPolicy, command,
59};
60pub use persistent::{
61    PersistentConfig, PersistentOutput, PersistentOutputStream, PersistentProcess,
62    PersistentReadiness, PersistentRun, PersistentStartErrorKind, PersistentStartup,
63    ShutdownOutcome, persistent_start_error_kind, start_persistent_with_cancel,
64};
65pub use process_group::{
66    interrupt as interrupt_process_group, isolate as isolate_process_group,
67    kill as kill_process_group, terminate as terminate_process_group,
68};
69pub use result::ProcessResult;
70pub use runner::{OutputObserver, run_with_cancel};
71pub use sync::run;
72
73/// Re-export error types
74pub use rskit_errors::{AppError, AppResult, ErrorCode};