Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
mmastrac committed Feb 8, 2024
1 parent 0707d62 commit a8d4c3b
Showing 1 changed file with 15 additions and 4 deletions.
19 changes: 15 additions & 4 deletions test_util/src/spawn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,21 @@ pub fn exec_replace_inner(
use win32job::ExtendedLimitInfo;
use win32job::Job;

// Creates a child process, and then assigns it to our current job. It would be more reliable
// to create the child suspended and then assign it to the job. For now, we create the child, create
// the job and then assign both us and the child to the job.
// Use a job to ensure the child process's lifetime does not exceed the current process's lifetime.
// This ensures that if the current process is terminated (e.g., via ctrl+c or task manager),
// the child process is automatically reaped.

// For more information about this technique, see Raymond Chen's blog post:
// https://devblogs.microsoft.com/oldnewthing/20131209-00/?p=2433
// Note: While our implementation is not perfect, it serves its purpose for test code.

// In the future, we may directly obtain the main thread's handle from Rust code and use it
// to create a suspended process that we can then resume:
// https://github.com/rust-lang/rust/issues/96723

// Creates a child process and assigns it to our current job.
// A more reliable approach would be to create the child suspended and then assign it to the job.
// For now, we create the child, create the job, and then assign both us and the child to the job.
let mut child = Command::new(cmd).args(&args[1..]).spawn()?;

let mut info = ExtendedLimitInfo::default();
Expand All @@ -53,8 +61,11 @@ pub fn exec_replace_inner(
std::process::exit(exit.code().unwrap_or(1));
}

/// Runs a command, replacing the current process. On Windows, this function blocks and
/// Runs a command, replacing the current process on Unix. On Windows, this function blocks and
/// exits.
///
/// In either case, the only way this function returns is if it fails to launch the child
/// process.
pub fn exec_replace(command: &str, args: &[&str]) -> Result<Infallible, Error> {
exec_replace_inner(command, args)
}

0 comments on commit a8d4c3b

Please sign in to comment.