use tokio_util::sync::CancellationToken; /// Install a ctrl-c handler that triggers the returned token. /// /// The first ctrl-c cancels gracefully; a second ctrl-c terminates the process. pub fn install_ctrl_c() -> CancellationToken { let token = CancellationToken::new(); let trigger = token.clone(); tokio::spawn(async move { if let Err(e) = tokio::signal::ctrl_c().await { // Installing the handler failed — ctrl-c won't trigger a graceful // shutdown. Say so instead of failing silently; the user can still // kill the process, and the second-ctrl-c arm below would only fail // the same way, so bail out of the task. tracing::warn!("could not install ctrl-c handler: {e}; ctrl-c won't shut down cleanly"); return; } tracing::info!("ctrl-c received, shutting down"); trigger.cancel(); if tokio::signal::ctrl_c().await.is_ok() { tracing::warn!("second ctrl-c — exiting now"); std::process::exit(130); } }); token }