79637844

Date: 2025-05-25 16:13:08
Score: 0.5
Natty:
Report link

The control signal set off by Ctrl + C is indeed caught by a cmd.exe instance launched when running mvn.cmd.

Process tree when PowerShell is launched with its own GUI:

conhost.exe
└─ powershell.exe
   └─ rust_program.exe
      └─ cmd.exe /C mvn.cmd [...]
         └─ java.exe [...]
        ↑
   Control signal is propagated down from conhost.exe and caught by cmd.exe

One way to avoid this would be to launch java.exe with the right arguments directly, but it's very hard to maintain. But don't worry! There is a better way:

Catch Ctrl + C in the Rust code

The native Child::wait and Child::kill functions in the standard library both take &mut references, which means they can't be used at the same time. The shared_child crate was created just for this purpose!

The ctrlc crate can be used to catch the signal set off by Ctrl + C. Its signal handler can only take 'static and Send references (basically meaning it can't take references to a value made in a function), but we can use an Arc to share the SharedChild across the Send + 'static boundary.

use std::{
    process::{Command, ExitStatus},
    sync::Arc,
};
use shared_child::SharedChild;

fn run_maven(main_class: &str) -> std::io::Result<ExitStatus> {
    let mut command = Command::new("mvn.cmd")
        .args(&[
            "exec:java",
            &format!("-Dexec.mainClass={main_class}"),
            "-Dexec.cleanupDaemonThreads=false",
            "--quiet"
        ]);

    // Spawn the child process and wrap it in an Arc
    let child = Arc::new(SharedChild::spawn(&mut command)?);

    // Clone the Arc so it can be moved into the Ctrl+C handler's closure
    let child_clone = Arc::clone(&child);

    // Set the Ctrl+C handler to kill the child process when triggered
    ctrlc::set_handler(move || {
        eprintln!("\nCtrl-C pressed! Killing Maven");
        let _ = child_clone.kill();
    })
    .expect("Failed to set Ctrl-C handler");

    // Wait for the child to finish and return exit status
    child.wait()
}

Related: https://stackoverflow.com/a/78189047/30626125

Reasons:
  • Blacklisted phrase (1): stackoverflow
  • Long answer (-1):
  • Has code block (-0.5):
  • Low reputation (1):
Posted by: axka