From e91b64a4db07d8f2c43d6198483d5ec67ebcfc5f Mon Sep 17 00:00:00 2001 From: reverse Date: Wed, 12 Aug 2026 13:19:25 +0000 Subject: [PATCH] resilience: isolate per-connection panics in the plaintext reactor (catch_unwind read/write -> drop just that conn) and log worker-thread panics instead of vanishing silently --- src/server.rs | 10 ++++++++-- src/socketengine.rs | 18 ++++++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/server.rs b/src/server.rs index b644062..47c70de 100644 --- a/src/server.rs +++ b/src/server.rs @@ -479,8 +479,14 @@ impl Server { let tx = self.event_tx.clone(); std::thread::spawn(move || { let _guard = Guard; // decrements even on panic - let ev = f(); - let _ = tx.send(ev); + match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) { + Ok(ev) => { + let _ = tx.send(ev); + } + // a panic here can't reach the core (we don't know which Event to send); + // log it so a stuck request is diagnosable instead of silent. + Err(_) => eprintln!("[worker] a background crypto/http task panicked; its request was dropped"), + } }); true } diff --git a/src/socketengine.rs b/src/socketengine.rs index 20b80c8..d1b455f 100644 --- a/src/socketengine.rs +++ b/src/socketengine.rs @@ -351,11 +351,25 @@ pub fn run_reactor( } } Token(t) => { + // isolate per-connection I/O: a panic framing one client's bytes + // drops that client, never the reactor that serves all the others. if event.is_readable() { - read_conn(&mut poll, &mut conns, t, &core); + let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + read_conn(&mut poll, &mut conns, t, &core) + })); + if r.is_err() { + eprintln!("[reactor] recovered from a panic reading a socket; dropping that connection"); + close_conn(&mut poll, &mut conns, t, &core); + } } if event.is_writable() && conns.contains_key(&t) { - flush_conn(&mut poll, &mut conns, t, &core); + let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + flush_conn(&mut poll, &mut conns, t, &core) + })); + if r.is_err() { + eprintln!("[reactor] recovered from a panic writing a socket; dropping that connection"); + close_conn(&mut poll, &mut conns, t, &core); + } } } }