pub struct ProcessHandle { /* private fields */ }Expand description
Represents a handle to a process identified by its process ID (PID).
The ProcessHandle struct is used to encapsulate the process identifier (PID)
of a running process. It is designed to be lightweight and can be cloned
or debugged as required.
§Fields
pid: Au32value that represents the process ID of the targeted process.
§Traits
Debug: Allows instances ofProcessHandleto be formatted using the{:?}formatter for debugging purposes.Clone: Allows theProcessHandleto be cloned, creating a new instance with the samepid.
§Example
let handle = ProcessHandle { pid: 1234 };
println!("{:?}", handle); // Outputs: ProcessHandle { pid: 1234 }
let cloned_handle = handle.clone();
println!("{:?}", cloned_handle); // Outputs: ProcessHandle { pid: 1234 }Implementations§
Source§impl ProcessHandle
impl ProcessHandle
pub async fn receive_output(&mut self) -> Result<Option<String>>
Sourcepub async fn receive_output_with_timeout(
&mut self,
timeout: Duration,
) -> Result<Option<String>>
pub async fn receive_output_with_timeout( &mut self, timeout: Duration, ) -> Result<Option<String>>
Receives an output message asynchronously from the process associated with the instance’s pid
if available, with a specified timeout.
This function is similar to receive_output() but allows specifying a custom timeout duration
instead of using the default timeout.
§Arguments
timeout- Astd::time::Durationspecifying how long to wait for a message before giving up.
§Returns
Ok(Some(String))- If a message is successfully received from the receiver channel.Ok(None)- If no message is received before the timeout expires.Err(Error)- If an error occurs during the process, such as:- The process pool is not initialized
- The process with the specified PID is not found
- The receiver channel is not available
- The receiver channel is disconnected
§Example
// Wait for up to 5 seconds for a message
match instance.receive_output_with_timeout(std::time::Duration::from_secs(5)).await {
Ok(Some(output)) => println!("Received output: {}", output),
Ok(None) => println!("No output received within timeout."),
Err(e) => eprintln!("Error receiving output: {}", e),
}Sourcepub async fn send_input(&self, input: impl Into<String>) -> Result<()>
pub async fn send_input(&self, input: impl Into<String>) -> Result<()>
Sends the provided input to a process associated with this instance’s PID asynchronously.
§Arguments
input- An input of any type that can be converted into aString. This is the data that will be sent to the respective process’s input queue.
§Returns
Ok(())if the input was successfully sent or queued for sending.Err- Returns an error in the following cases:- If the process pool is not initialized.
- If the process associated with this PID is not found.
- If the process was not started or its sender channel is not available.
- If the sender channel is closed and input cannot be sent.
§Details
This function retrieves the process associated with the current instance’s pid
from a global process pool. If a valid process is found:
- The input is sent via an asynchronous channel to the process.
- If the channel is full, the input is queued for later sending.
- If the channel is closed, an error is returned.
The function also ensures thread safety by acquiring a lock on the process pool before attempting any operations related to the process.
§Errors
This function propagates several potential issues as errors:
- If the process pool is uninitialized (
PROCESS_POOL.get()returnsNone). - If the process associated with the PID is missing in the pool.
- If the sender channel was never initialized or is unavailable.
- If the sender channel is closed and no new messages can be sent.
§Example
use anyhow::Result;
#[tokio::main]
async fn main() -> Result<()> {
let manager = ProcessManager::new(1); // Assumes a struct is managing process with ID 1.
manager.send_input("Some input").await?;
Ok(())
}§Note
This function expects a global process pool (PROCESS_POOL) to be properly initialized before being called.
Additionally, the associated process must have a valid sender channel to accept input.
Sourcepub async fn is_process_running(&self) -> bool
pub async fn is_process_running(&self) -> bool
Checks if the process associated with the current instance is running.
This method attempts to determine if a process with the pid of the current instance
exists in the global PROCESS_POOL.
§Returns
true- If the process with the associatedpidis currently present in the global process pool.false- If the process is not found in the global process pool or if the pool is not initialized.
§Async Behavior
This method is asynchronous because it acquires a lock on the PROCESS_POOL.
§Notes
- The
PROCESS_POOLmust be initialized before calling this function. IfPROCESS_POOLis not set, the function will returnfalse. - The
PROCESS_POOLis expected to be a globally accessible, asynchronous, and thread-safe data structure that tracks active processes.
§Example
let result = instance.is_process_running().await;
if result {
println!("Process is running.");
} else {
println!("Process is not running.");
}Sourcepub async fn shutdown(&self, timeout: Duration) -> Result<()>
pub async fn shutdown(&self, timeout: Duration) -> Result<()>
Asynchronously terminates a process identified by its pid.
This method performs the following operations tailored to the target operating system:
- Windows: Opens a handle to the process using its process ID (
pid) and forcefully terminates it using theTerminateProcessfunction from the WinAPI. - Linux: Utilizes the
killsystem call with theSIGKILLsignal to forcefully terminate the process.
§Platform-specific Notes:
- On Windows, the process is identified and terminated using the
OpenProcessandTerminateProcessfunctions from the WinAPI. - On Linux, the
killsystem call is used with the signalSIGKILL(9) to ensure the process is terminated.
§Errors
- Returns an error if the process termination fails (on Linux) due to system call errors or invalid process IDs.
On failure, the error contains details about the
pidand the last OS error encountered.
§Safety
This method uses unsafe code blocks to interact with system APIs (libc on Linux, WinAPI on Windows). Ensure
that the provided pid corresponds to a valid process, and consider the implications of forcefully
terminating processes.
§Example
let process_manager = SomeProcessManager::new(pid); // Example struct containing the pid
if let Err(e) = process_manager.kill().await {
eprintln!("Failed to terminate process: {}", e);
}Attempts to gracefully shut down the process, falling back to forceful termination if needed.
This method first tries to gracefully shut down the process by:
- On Linux: Sending a SIGTERM signal
- On Windows: Sending a WM_CLOSE message to the main window
If the process doesn’t exit within the specified timeout, it will forcefully terminate
the process using the kill() method.
§Arguments
timeout- Astd::time::Durationspecifying how long to wait for the process to exit gracefully before forcefully terminating it.
§Returns
Ok(())- If the process was successfully shut down (either gracefully or forcefully).Err(Error)- If an error occurred during the shutdown process.
§Example
// Try to shut down gracefully, waiting up to 5 seconds before force killing
if let Err(e) = process.shutdown(std::time::Duration::from_secs(5)).await {
eprintln!("Failed to shut down process: {}", e);
}Sourcepub async fn kill(&self) -> Result<()>
pub async fn kill(&self) -> Result<()>
Forcefully terminates the process immediately.
This method should be used as a last resort when a process needs to be terminated
immediately. For a more graceful approach, consider using shutdown() first.
§Returns
Ok(())- If the process was successfully terminated.Err(Error)- If an error occurred during the termination process.
§Example
if let Err(e) = process.kill().await {
eprintln!("Failed to terminate process: {}", e);
}