diff --git a/Cargo.lock b/Cargo.lock index b9b1100..de4c7bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,6 +101,7 @@ dependencies = [ "anyhow", "bytemuck", "chrono", + "futures", "hyper", "serde", "serde_json", @@ -194,6 +195,20 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "futures" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.27" @@ -201,6 +216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -209,6 +225,18 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" +[[package]] +name = "futures-io" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91" + +[[package]] +name = "futures-sink" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" + [[package]] name = "futures-task" version = "0.3.27" @@ -221,10 +249,15 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -512,6 +545,15 @@ dependencies = [ "serde", ] +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + [[package]] name = "socket2" version = "0.4.9" diff --git a/Cargo.toml b/Cargo.toml index 02f1154..156da00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ serde = { version = "1.0.152", features = ["derive"] } serde_json = "1.0.91" hyper = { version = "0.14.24", optional = true, features = ["server", "http1", "tcp"] } chrono = { version = "0.4.23", optional = true } +futures = { version = "0.3.27", default-features = false, features = ["std"] } [features] default = ["debug_server", "chrono"] diff --git a/src/main.rs b/src/main.rs index 55c5b77..f14729a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -91,13 +91,6 @@ impl Config { #[tokio::main] async fn main() -> anyhow::Result<()> { - // make whole programm exit on worker thread crash - let default_panic = std::panic::take_hook(); - std::panic::set_hook(Box::new(move |info| { - default_panic(info); - std::process::exit(1); - })); - let config = Arc::new(Config::load("config.json")?); if config.allowed_ports.is_empty() { @@ -127,7 +120,9 @@ async fn main() -> anyhow::Result<()> { if should_store { last_store = Some(last_update); - port_handler.store(&cache_path).unwrap(); + if let Err(err) = port_handler.store(&cache_path) { + println!("failed to store cache: {err:?}"); + } } } } @@ -152,17 +147,36 @@ async fn main() -> anyhow::Result<()> { let mut handler_metadata = HandlerMetadata::default(); tokio::spawn(async move { - let res = - connection_handler(&config, &mut handler_metadata, &port_handler, &mut stream) - .await; + use futures::future::FutureExt; - if let Err(err) = res { - println!("client at {addr} had an error: {err:?}"); + let res = std::panic::AssertUnwindSafe(connection_handler( + &config, + &mut handler_metadata, + &port_handler, + &mut stream, + )) + .catch_unwind() + .await; + + let error = match res { + Err(err) => { + let err = err + .downcast::() + .unwrap_or_else(|_| Box::new("?".to_owned())); + + Some(format!("panic at: {err}")) + } + Ok(Err(err)) => Some(err.to_string()), + Ok(Ok(())) => None, + }; + + if let Some(err) = error { + println!("client at {addr} had an error: {err}"); let mut packet = Packet::default(); - packet.data.extend_from_slice(err.to_string().as_bytes()); - packet.data.truncate(0xfe); + packet.data.extend_from_slice(err.as_bytes()); + packet.data.truncate((u8::MAX - 1) as usize); packet.data.push(0); packet.header = Header { kind: PacketKind::Error.raw(), diff --git a/src/ports.rs b/src/ports.rs index 5c05ef0..d919510 100644 --- a/src/ports.rs +++ b/src/ports.rs @@ -198,7 +198,7 @@ impl PortHandler { } pub fn store(&self, cache: &Path) -> anyhow::Result<()> { - println!("storing database"); + println!("storing cache"); let temp_file = cache.with_extension(".temp"); serde_json::to_writer(BufWriter::new(File::create(&temp_file)?), self)?; @@ -208,7 +208,7 @@ impl PortHandler { } pub fn load(cache: &Path) -> std::io::Result { - println!("loading database"); + println!("loading cache"); Ok(serde_json::from_reader(BufReader::new(File::open(cache)?))?) }