diff options
| author | Mroik <mroik@delayed.space> | 2026-04-11 04:02:53 +0200 |
|---|---|---|
| committer | Mroik <mroik@delayed.space> | 2026-04-13 06:56:11 +0200 |
| commit | ffc0ad7c86408193b213c46cbca5c0d8b60f8632 (patch) | |
| tree | 2612530158ed0a2529f866e23f324758011efcfd | |
| parent | b336fd39444e8089d35a7a2bd4c0c3e8228c6c36 (diff) | |
Do not propagate TcpListener.accept() errors
Errors produced by the socket may not be necessarily fatal, meaning that
while a connection might be dropped the process should be able to resume
execution as if nothing happened and accept the next connection.
Error handling for accept() has been copied from NGINX's [1].
[1] https://stackoverflow.com/questions/76955978/which-socket-accept-errors-are-fatal
Signed-off-by: Mroik <mroik@delayed.space>
| -rw-r--r-- | Cargo.lock | 7 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/smtp_server.rs | 16 |
3 files changed, 23 insertions, 1 deletions
@@ -207,6 +207,12 @@ dependencies = [ ] [[package]] +name = "libc" +version = "0.2.184" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" + +[[package]] name = "libsqlite3-sys" version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -273,6 +279,7 @@ version = "0.1.0" dependencies = [ "anyhow", "env_logger", + "libc", "log", "rusqlite", "tokio", @@ -6,6 +6,7 @@ edition = "2024" [dependencies] anyhow = "1.0.102" env_logger = "0.11.10" +libc = "0.2.184" log = "0.4.29" rusqlite = "0.39.0" tokio = { version = "1.51.0", features = ["macros", "rt-multi-thread", "sync"] } diff --git a/src/smtp_server.rs b/src/smtp_server.rs index bacf8eb..e6c0efc 100644 --- a/src/smtp_server.rs +++ b/src/smtp_server.rs @@ -27,7 +27,21 @@ impl SmtpServer { pub async fn run(&mut self, tx_processor: Sender<Mail>) -> Result<()> { self.running = true; while self.running { - let (stream, addr) = self.listener.accept()?; + let (stream, addr) = match self.listener.accept() { + Ok(v) => v, + Err(e) => match e.raw_os_error() { + Some(libc::EMFILE | libc::ENFILE) => return Err(anyhow::Error::from(e)), + Some(libc::ECONNABORTED) => { + log::error!("{}", e); + continue; + } + Some(libc::EAGAIN) => continue, + _ => { + log::warn!("{}", e); + continue; + } + }, + }; let session = SessionHandler { addr, tx_processor: tx_processor.clone(), |
