pub struct ProcessGroup { /* private fields */ }Expand description
A cross-platform wrapper for managing process groups/jobs.
On Unix systems, this uses process groups with setsid().
On Windows, this uses Job Objects for full process tree termination.
§Platform Support
- Unix/Linux: Full process group support using
setsid()andkillpg() - Windows: Full process tree support using Job Objects
- Other platforms: No special handling
Implementations§
Source§impl ProcessGroup
impl ProcessGroup
Sourcepub fn pause_group(&self) -> Result<(), ProcessGroupError>
pub fn pause_group(&self) -> Result<(), ProcessGroupError>
Pauses all processes in the group (Unix).
Sends SIGSTOP to the process group using killpg().
§Returns
Ok(())- If the signal was sent successfully or processes were already stoppedErr(ProcessGroupError)- If pausing fails due to permissions or other errors
§Example
use tcrm_task::tasks::process::group::builder::ProcessGroup;
let mut group = ProcessGroup::new();
// ... spawn processes in the group ...
group.pause_group().unwrap();Source§impl ProcessGroup
impl ProcessGroup
Sourcepub fn resume_group(&self) -> Result<(), ProcessGroupError>
pub fn resume_group(&self) -> Result<(), ProcessGroupError>
Resumes all processes in the group (Unix).
Sends SIGCONT to the process group using killpg().
§Returns
Ok(())- If the signal was sent successfullyErr(ProcessGroupError)- If resuming fails due to permissions or other errors
§Example
use tcrm_task::tasks::process::group::builder::ProcessGroup;
let mut group = ProcessGroup::new();
// ... spawn and pause processes in the group ...
group.resume_group().unwrap();Source§impl ProcessGroup
impl ProcessGroup
Sourcepub fn stop_group(&self) -> Result<(), ProcessGroupError>
pub fn stop_group(&self) -> Result<(), ProcessGroupError>
Terminates all processes in the group (Unix).
Sends SIGTERM to the process group using killpg().
§Returns
Ok(())- If the signal was sent successfully or processes were already terminatedErr(ProcessGroupError)- If termination fails due to permissions or other errors
§Example
use tcrm_task::tasks::process::group::builder::ProcessGroup;
let mut group = ProcessGroup::new();
// ... spawn processes in the group ...
group.stop_group().unwrap();Source§impl ProcessGroup
impl ProcessGroup
Sourcepub fn create_with_command(
&mut self,
command: Command,
) -> Result<Command, ProcessGroupError>
pub fn create_with_command( &mut self, command: Command, ) -> Result<Command, ProcessGroupError>
Creates a new process group and configures the command to use it.
This method prepares a Command to run as part of this process group. On Unix systems, it configures the command to create a new session and process group using setsid(). On Windows, it configures the command to run in a new job object with appropriate creation flags and enables CREATE_SUSPENDED to avoid race conditions.
§Arguments
command- The Command to configure for process group execution
§Returns
Ok(Command)- The configured command ready for executionErr(ProcessGroupError)- If process group configuration fails
§Platform-Specific Behavior
§Windows Race Condition Mitigation
On Windows, the process is configured to start in a suspended state (CREATE_SUSPENDED).
After spawning, you must call assign_child() and then manually resume the process
to avoid the race condition where child processes can escape the job before assignment.
§Unix Behavior
On Unix, the process starts normally in its own process group via setsid().
§Example
use tcrm_task::tasks::process::group::builder::ProcessGroup;
use tokio::process::Command;
let mut group = ProcessGroup::new();
let mut cmd = Command::new("echo");
cmd.arg("hello");
let configured_cmd = group.create_with_command(cmd).unwrap();
// Command is now configured to run in the process groupSourcepub fn assign_child(&mut self, child_id: u32) -> Result<(), ProcessGroupError>
pub fn assign_child(&mut self, child_id: u32) -> Result<(), ProcessGroupError>
Assigns a spawned child process to this process group/job.
On Unix systems, this stores the process group ID.
On Windows, this assigns the process to the job object.
After assignment, all future children of the process will be contained in the job, unless the process has breakaway privileges (which are not enabled by default in this implementation).
§Arguments
child_id- The process ID of the child to assign to this group
§Returns
Ok(())- If the assignment was successfulErr(ProcessGroupError)- If assignment fails or the platform is unsupported
§Example
use tcrm_task::tasks::process::group::builder::ProcessGroup;
use std::process::Command;
let mut group = ProcessGroup::new();
// After spawning a process, assign it to the group
// let child = Command::new("echo").spawn()?;
// group.assign_child(child.id())?;§Windows Race Condition Note
On Windows, there is a well-known race condition: if a spawned process creates child processes before it is assigned to the job object, those children will not be part of the job and can escape containment.
See: https://devblogs.microsoft.com/oldnewthing/20130405-00/?p=4743
To avoid this issue, the process needs to be spawned in a suspended state, assigned to the job object, and only then resuming it. This ensures that no child processes can escape the job before assignment.
Sourcepub fn resume_process(&self, _child_id: u32) -> Result<(), ProcessGroupError>
pub fn resume_process(&self, _child_id: u32) -> Result<(), ProcessGroupError>
No-op on non-Windows platforms.