Why always return 1 after handling ctrl-c?

std impl with ctrlc crate:

fn main() {
    let (close_tx, close_rx) = std::sync::mpsc::sync_channel::<()>(0);
    ctrlc::set_handler(move || close_tx.send(()).unwrap()).unwrap();
    for _ in 0..50 {
        if let Ok(()) = close_rx.try_recv() {
            break;
        }
        std::thread::sleep(std::time::Duration::from_millis(100));
    }
    // std::process::exit(0);
}

tokio impl:

#[tokio::main]
async fn main() {
    let (close_tx, mut close_rx) = tokio::sync::oneshot::channel::<()>();
    tokio::spawn(async move {
        tokio::signal::ctrl_c().await.unwrap();
        close_tx.send(()).unwrap();
    });
    for _ in 0..50 {
        if let Ok(()) = close_rx.try_recv() {
            break;
        }
        tokio::time::sleep(std::time::Duration::from_millis(100)).await;
    }
    // std::process::exit(0);
}

Both 2 impls make the process return 1 rather than the normal 0 after handling ctrl-c, whether the std::process::exit(0); is added or not. But running with cargo run will not get the process didn't exit successfully prompt. For comparison, if a std::process::exit(1); is added, it will get the prompt.

When you hit ctrl-C during cargo run, cargo itself also receives the signal and is terminated before it has a chance to print "process didn't exit successfully".

1 Like