diff --git a/Cargo.toml b/Cargo.toml index 9e1f2106b..fa2adc6c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ tokio = { version = "1.41", features = [ "rt-multi-thread", "sync", "io-std", + "signal", ] } thiserror = "1.0" diff --git a/pumpkin/Cargo.toml b/pumpkin/Cargo.toml index 5e83ea919..52dbafc02 100644 --- a/pumpkin/Cargo.toml +++ b/pumpkin/Cargo.toml @@ -37,8 +37,6 @@ rand = "0.8.5" num-bigint = "0.4" -ctrlc = "3.4" - # encryption rsa = "0.9.6" rsa-der = "0.3.0" diff --git a/pumpkin/src/main.rs b/pumpkin/src/main.rs index 9823afdad..038ceb596 100644 --- a/pumpkin/src/main.rs +++ b/pumpkin/src/main.rs @@ -25,6 +25,10 @@ use client::Client; use server::{ticker::Ticker, Server}; use std::io::{self}; use tokio::io::{AsyncBufReadExt, BufReader}; +#[cfg(not(unix))] +use tokio::signal::ctrl_c; +#[cfg(unix)] +use tokio::signal::unix::{signal, SignalKind}; use std::sync::Arc; @@ -94,16 +98,13 @@ async fn main() -> io::Result<()> { // .enable_all() // .build() // .unwrap(); - ctrlc::set_handler(|| { - log::warn!( - "{}", - TextComponent::text("Stopping Server") - .color_named(NamedColor::Red) - .to_pretty_console() - ); - std::process::exit(0); - }) - .unwrap(); + + tokio::spawn(async { + setup_sighandler() + .await + .expect("Unable to setup signal handlers"); + }); + // ensure rayon is built outside of tokio scope rayon::ThreadPoolBuilder::new().build_global().unwrap(); let default_panic = std::panic::take_hook(); @@ -203,6 +204,44 @@ async fn main() -> io::Result<()> { } } +fn handle_interrupt() { + log::warn!( + "{}", + TextComponent::text("Received interrupt signal; stopping server...") + .color_named(NamedColor::Red) + .to_pretty_console() + ); + std::process::exit(0); +} + +// Non-UNIX Ctrl-C handling +#[cfg(not(unix))] +async fn setup_sighandler() -> io::Result<()> { + if ctrl_c().await.is_ok() { + handle_interrupt(); + } + + Ok(()) +} + +// Unix signal handling +#[cfg(unix)] +async fn setup_sighandler() -> io::Result<()> { + if signal(SignalKind::interrupt())?.recv().await.is_some() { + handle_interrupt(); + } + + if signal(SignalKind::hangup())?.recv().await.is_some() { + handle_interrupt(); + } + + if signal(SignalKind::terminate())?.recv().await.is_some() { + handle_interrupt(); + } + + Ok(()) +} + fn setup_console(server: Arc) { tokio::spawn(async move { let stdin = tokio::io::stdin();