pub struct AsynchronousInteractiveProcess {
pub pid: Option<u32>,
pub filename: String,
pub arguments: Vec<String>,
pub working_directory: PathBuf,
/* private fields */
}Expand description
AsynchronousInteractiveProcess is a structure that represents a non-blocking,
interactive process. It provides metadata and mechanisms to interact with a
process asynchronously using sender and receiver channels.
§Fields
-
pid- An optional process ID (pid) of the interactive process. If the process is not yet started, this field will remainNone. -
filename- The name of the executable file that represents the interactive process. This is required to identify and initiate the process. -
arguments- A vector containing the arguments to pass to the executable file when launching the process. -
working_directory- The directory where the interactive process will be executed. This is represented as aPathBuf. -
sender- An optionalSenderchannel used to send messages or data to the interactive process. This field is skipped during serialization and deserialization because it holds runtime-related data. -
receiver- An optionalReceiverchannel used to receive messages or data from the interactive process. This field is also skipped during serialization and deserialization for the same reasons assender. -
input_queue- A deque (double-ended queue) that maintains an in-memory buffer of strings representing input for the interactive process. This field is skipped during serialization as it only contains transient runtime-related data.
§Trait Implementations
Debug: Allows instances of this struct to be formatted and logged for debugging purposes.Serialize: Makes the struct serializable, excluding fields marked with#[serde(skip)].Deserialize: Allows deserialization to create instances of this struct from serialized data.Default: Provides a default implementation where optional fields are set toNone, collections are empty, andfilenameis an empty string.
§Example
use std::path::PathBuf;
use std::collections::VecDeque;
use serde::{Serialize, Deserialize};
use crossbeam_channel::{Sender, Receiver};
let process = AsynchronousInteractiveProcess {
pid: None,
filename: "my_program".to_string(),
arguments: vec!["--help".to_string()],
working_directory: PathBuf::from("/path/to/dir"),
sender: None,
receiver: None,
input_queue: VecDeque::new(),
};
println!("{:?}", process);This structure is ideal for scenarios where processes need to be controlled asynchronously with multiple input or output channels.
Fields§
§pid: Option<u32>§filename: String§arguments: Vec<String>§working_directory: PathBufImplementations§
Source§impl AsynchronousInteractiveProcess
impl AsynchronousInteractiveProcess
Sourcepub fn new(filename: impl Into<String>) -> Self
pub fn new(filename: impl Into<String>) -> Self
Creates a new instance of the struct with default values.
§Arguments
filename- A value that can be converted into aString. This typically represents the name or path of the file associated with the instance.
§Returns
Returns a new instance of the struct populated with default fields:
pid:None(indicating no process ID is associated yet).filename: The providedfilenameconverted into aString.arguments: An empty vector, representing no initial arguments.working_directory: Set to the current directory ("./").sender:None, indicating no sender is associated initially.receiver:None, indicating no receiver is associated initially.input_queue: An emptyVecDeque, representing no items in the input queue.
§Example
let instance = MyStruct::new("example.txt");
assert_eq!(instance.filename, "example.txt");
assert!(instance.pid.is_none());
assert!(instance.arguments.is_empty());
assert_eq!(instance.working_directory, PathBuf::from("./"));
assert!(instance.sender.is_none());
assert!(instance.receiver.is_none());
assert!(instance.input_queue.is_empty());Sourcepub fn with_arguments(self, args: Vec<impl Into<String>>) -> Self
pub fn with_arguments(self, args: Vec<impl Into<String>>) -> Self
Sets the arguments for the current instance by converting a vector of items
implementing Into<String> into a Vec<String>.
§Parameters
args: AVeccontaining items that implement theInto<String>trait. These items will be converted intoStringand used to set theargumentsfield of the instance.
§Returns
Self: The current instance (self) after updating itsargumentsfield.
§Example
let instance = MyStruct::new()
.with_arguments(vec!["arg1", "arg2", String::from("arg3")]);This method allows chaining, as it returns the updated instance
after setting the arguments field.
Sourcepub fn with_argument(self, arg: impl Into<String>) -> Self
pub fn with_argument(self, arg: impl Into<String>) -> Self
Adds an argument to the arguments vector and returns the modified instance.
§Parameters
arg- A value that implements theInto<String>trait, which will be converted into aStringand added to theargumentsvector.
§Returns
Returns the modified instance of the implementing struct (Self) with the new argument added.
§Example
let instance = SomeStruct::new().with_argument("example");This adds the string "example" to the arguments vector of SomeStruct.
Sourcepub fn with_working_directory(self, dir: impl Into<PathBuf>) -> Self
pub fn with_working_directory(self, dir: impl Into<PathBuf>) -> Self
Sets the working directory for the instance and returns the modified instance.
§Arguments
dir- A value that can be converted into aPathBuf, representing the desired working directory.
§Returns
The instance of the struct with the updated working directory.
§Example
let instance = MyStruct::new()
.with_working_directory("/path/to/directory");pub fn process_exit_callback<F>(self, callback: F) -> Self
Sourcepub async fn start(&mut self) -> Result<u32>
pub async fn start(&mut self) -> Result<u32>
Starts a new process based on the configuration stored in the struct, manages its I/O streams asynchronously, and tracks its lifecycle in a shared process pool.
§Returns
Ok<u32>: Returns the process ID (PID) if the process starts successfully.Err(std::io::Error): Returns an error if any part of the process start operation fails.
§Process Configuration
- The process is launched using the executable specified in
self.filename. - Command-line arguments are passed via
self.arguments. - The process will run in the directory specified in
self.working_directory.
§Standard I/O Management
- The process’s
stdinis assigned atokio::sync::mpsc::channelfor communication. stdoutandstderrare read asynchronously. Each line from these streams is sent to anmpsc::channel, wherestdout/stderrdata can be consumed.
§Shared Process Pool
- The process metadata, including its PID and I/O channels, is stored in a global,
thread-safe
PROCESS_POOL. - The process pool is managed using a
tokio::sync::Mutexand stores processes in aHashMapwith their PID as the key.
§Asynchronous I/O
- A background task is spawned to write data from an internal input queue to the process’s
stdin. - Another background task continuously reads and forwards
stdoutandstderrmessages from the process. - If the process exits or encounters an error, its PID and metadata are removed from the process pool.
§Example Use Case
let mut my_process = MyProcess {
filename: "my_program".to_string(),
arguments: vec!["--arg1", "value1".to_string()],
working_directory: "/path/to/dir".to_string(),
pid: None,
sender: None,
receiver: None,
input_queue: VecDeque::new(),
};
let pid = my_process.start().await.unwrap();
println!("Started process with PID: {}", pid);§Notes
- The process’s
stdin,stdout, andstderrare piped to capture and manage communication asynchronously. - Each spawned background task is independently responsible for managing a specific stream or part of the process lifecycle.
- Errors during I/O operations or spawning the process are logged using the
logcrate macros (e.g.,error!,debug!).
§Potential Errors
- Failure to spawn the process (e.g., if
self.filenameis invalid or inaccessible). - Errors during communication with the process’s I/O streams (e.g., writing to a closed
stdin). - Mutex locking failure on the shared process pool due to an internal inconsistency.
Sourcepub async fn get_process_by_pid(pid: u32) -> Option<ProcessHandle>
pub async fn get_process_by_pid(pid: u32) -> Option<ProcessHandle>
Asynchronously retrieves a handle to a process for a given process ID (PID).
This function checks if a process with the specified PID exists in a shared
process pool. If the process is found, it returns an Option containing a
ProcessHandle for the process. Otherwise, it returns None.
§Arguments
pid- A 32-bit unsigned integer representing the process ID of the desired process.
§Returns
Some(ProcessHandle)- If a process with the given PID is found in the process pool.None- If the process does not exist in the process pool or if the process pool is uninitialized.
§Example
if let Some(handle) = get_process_by_pid(12345).await {
println!("Process found with PID: {}", handle.pid);
} else {
println!("Process not found.");
}§Errors
This function will return None if the global process pool (PROCESS_POOL)
has not been initialized or is unavailable.
§Note
This is an asynchronous function and must be awaited to complete its operation.
Sourcepub async fn is_process_running(&self) -> bool
pub async fn is_process_running(&self) -> bool
Asynchronously checks if a process identified by its pid is currently running.
§Returns
trueif the process with the storedpidis found in thePROCESS_POOL.falseif the storedpidisNone, thePROCESS_POOLis not initialized, or thepiddoes not exist in thePROCESS_POOL.
The function first checks if the pid instance variable is set. If so, it attempts
to access the global PROCESS_POOL. If PROCESS_POOL is initialized, it acquires
a lock and checks if the pid exists in the pool.
§Examples
let result = my_instance.is_process_running().await;
if result {
println!("The process is running.");
} else {
println!("The process is not running.");
}§Async Behavior
This function acquires an asynchronous lock on the PROCESS_POOL to safely access
its contents and will yield if the lock is currently held elsewhere.
§Panics
This function may panic if the async lock on the PROCESS_POOL fails unexpectedly.
§Dependencies
PROCESS_POOLshould be a globally accessible and lazily initialized structure (e.g., usingonce_cellor similar patterns) that maintains a mapping of currently active processes.