fix: do not crash if accepting new connection fails

If we run out of file descriptors, we cannot do anything
to accept queued connections, so at least don't crash the process.
Fixes <https://github.com/chatmail/filtermail/issues/139>.
This commit is contained in:
link2xt
2026-05-14 20:59:59 +00:00
committed by l
parent 664ad571b6
commit 847e19546b
2 changed files with 36 additions and 18 deletions
+18 -9
View File
@@ -8,6 +8,7 @@ use hyper_util::rt::TokioIo;
use std::convert::Infallible; use std::convert::Infallible;
use std::pin::Pin; use std::pin::Pin;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use tokio::net::{TcpListener, TcpStream}; use tokio::net::{TcpListener, TcpStream};
/// Runs the HTTP server on the specified address with the given handler and maximum message size. /// Runs the HTTP server on the specified address with the given handler and maximum message size.
@@ -21,17 +22,25 @@ where
{ {
let listener = TcpListener::bind(addr).await?; let listener = TcpListener::bind(addr).await?;
loop { loop {
let (socket, _) = listener.accept().await?; match listener.accept().await {
Ok((socket, _peer_addr)) => {
// Disable Nagle's algorithm.
socket.set_nodelay(true)?;
// Disable Nagle's algorithm. let handler = handler.clone();
socket.set_nodelay(true)?; tokio::spawn(async move {
if let Err(e) = handle_connection(socket, handler, max_size).await {
let handler = handler.clone(); log::error!("Error handling connection: {e}");
tokio::spawn(async move { }
if let Err(e) = handle_connection(socket, handler, max_size).await { });
log::error!("Error handling connection: {e}");
} }
}); Err(e) => {
log::error!("Error accepting connection: {e}");
// Sleep to avoid busy looping in case we ran into file descriptor limit.
tokio::time::sleep(Duration::from_secs(10)).await;
}
}
} }
} }
+18 -9
View File
@@ -4,6 +4,7 @@ use crate::utils::{extract_address, log_eml};
use async_trait::async_trait; use async_trait::async_trait;
use memchr::{Memchr, memmem}; use memchr::{Memchr, memmem};
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader, BufWriter}; use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader, BufWriter};
use tokio::net::{TcpListener, TcpStream}; use tokio::net::{TcpListener, TcpStream};
@@ -110,17 +111,25 @@ where
log::info!("entering serving loop"); log::info!("entering serving loop");
loop { loop {
let (socket, _) = listener.accept().await?; match listener.accept().await {
Ok((socket, _peer_addr)) => {
// Disable Nagle's algorithm.
socket.set_nodelay(true)?;
// Disable Nagle's algorithm. let handler = handler.clone();
socket.set_nodelay(true)?; tokio::spawn(async move {
if let Err(e) = handle_connection(socket, handler, max_size).await {
let handler = handler.clone(); log::error!("Error handling connection: {e}");
tokio::spawn(async move { }
if let Err(e) = handle_connection(socket, handler, max_size).await { });
log::error!("Error handling connection: {e}");
} }
}); Err(e) => {
log::error!("Error accepting connection: {e}");
// Sleep to avoid busy looping in case we ran into file descriptor limit.
tokio::time::sleep(Duration::from_secs(10)).await;
}
}
} }
} }