Skip to content

Commit

Permalink
fix: http servers closijng after non-fatal errors
Browse files Browse the repository at this point in the history
  • Loading branch information
TroyKomodo committed Oct 26, 2024
1 parent aaefa13 commit 020d2d0
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 5 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion foundations/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ thiserror = { version = "1", optional = true }
http-body = { version = "1", optional = true }
socket2 = { version = "0.5", optional = true }

libc = { version = "0.2", optional = true }

[features]

context = [
Expand Down Expand Up @@ -203,7 +205,8 @@ http = [
"futures",
"context",
"socket2",
"tracing"
"tracing",
"libc"
]

http-tls = [
Expand Down
12 changes: 12 additions & 0 deletions foundations/src/http/server/stream/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,15 @@ impl ActiveRequestsGuard {
Self(active_requests)
}
}

fn is_fatal_tcp_error(err: &std::io::Error) -> bool {
matches!(
err.raw_os_error(),
Some(libc::EFAULT)
| Some(libc::EINVAL)
| Some(libc::ENFILE)
| Some(libc::EMFILE)
| Some(libc::ENOBUFS)
| Some(libc::ENOMEM)
)
}
15 changes: 13 additions & 2 deletions foundations/src/http/server/stream/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use tracing::Instrument;

use super::{Backend, IncomingConnection, MakeService, ServiceHandler, SocketKind};
use crate::context::ContextFutExt;
use crate::http::server::stream::{jitter, ActiveRequestsGuard};
use crate::http::server::stream::{is_fatal_tcp_error, jitter, ActiveRequestsGuard};
#[cfg(feature = "runtime")]
use crate::runtime::spawn;
#[cfg(feature = "opentelemetry")]
Expand Down Expand Up @@ -83,10 +83,21 @@ impl Backend for TcpBackend {

tracing::trace!("waiting for incoming connection");

let Some((connection, addr)) = self.listener.accept().with_context(&ctx).await.transpose()? else {
let Some(stream) = self.listener.accept().with_context(&ctx).await else {
break;
};

let (connection, addr) = match stream {
Ok((connection, addr)) => (connection, addr),
Err(err) if is_fatal_tcp_error(&err) => {
return Err(err.into());
}
Err(err) => {
tracing::error!(err = %err, "failed to accept connection");
continue;
}
};

let span = tracing::trace_span!("connection", remote_addr = %addr);

let _guard = span.enter();
Expand Down
15 changes: 13 additions & 2 deletions foundations/src/http/server/stream/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use tracing::Instrument;

use super::{Backend, IncomingConnection, MakeService, ServiceHandler, SocketKind};
use crate::context::ContextFutExt;
use crate::http::server::stream::{jitter, ActiveRequestsGuard};
use crate::http::server::stream::{is_fatal_tcp_error, jitter, ActiveRequestsGuard};
#[cfg(feature = "runtime")]
use crate::runtime::spawn;
#[cfg(feature = "opentelemetry")]
Expand Down Expand Up @@ -91,10 +91,21 @@ impl Backend for TlsBackend {

tracing::trace!("waiting for incoming connection");

let Some((connection, addr)) = self.listener.accept().with_context(&ctx).await.transpose()? else {
let Some(stream) = self.listener.accept().with_context(&ctx).await else {
break;
};

let (connection, addr) = match stream {
Ok((connection, addr)) => (connection, addr),
Err(err) if is_fatal_tcp_error(&err) => {
return Err(err.into());
}
Err(err) => {
tracing::error!(err = %err, "failed to accept connection");
continue;
}
};

let span = tracing::trace_span!("connection", remote_addr = %addr);
let _guard = span.enter();

Expand Down

0 comments on commit 020d2d0

Please sign in to comment.