Skip to content

Commit 7bc3493

Browse files
committed
listen:detect backlog parameter as in std. library
Define the `listen` backlog parameters as in the standard library. On one hand, this helps avoid hardcoded or unsynchronized values. On the other hand, it allows better control of default values depending on the target. This is an initial version which deals with issue #1872
1 parent cd97297 commit 7bc3493

File tree

6 files changed

+64
-8
lines changed

6 files changed

+64
-8
lines changed

src/net/tcp/listener.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::{fmt, io};
1313

1414
use crate::io_source::IoSource;
1515
use crate::net::TcpStream;
16+
use crate::sys::get_listen_backlog_size;
1617
#[cfg(any(unix, target_os = "hermit"))]
1718
use crate::sys::tcp::set_reuseaddr;
1819
#[cfg(not(target_os = "wasi"))]
@@ -78,7 +79,7 @@ impl TcpListener {
7879
set_reuseaddr(&listener.inner, true)?;
7980

8081
bind(&listener.inner, addr)?;
81-
listen(&listener.inner, 1024)?;
82+
listen(&listener.inner, get_listen_backlog_size())?;
8283
Ok(listener)
8384
}
8485

src/sys/mod.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,60 @@ cfg_not_os_poll! {
8080
pub use self::unix::SourceFd;
8181
}
8282
}
83+
84+
/// Define the `listen` backlog parameters as in the standard library. This
85+
/// helps avoid hardcoded unsynchronized values and allows better control of
86+
/// default values depending on the target.
87+
///
88+
/// Selecting a “valid” default value can be tricky due to:
89+
///
90+
/// - It often serves only as a hint and may be rounded, trimmed, or ignored by
91+
/// the OS.
92+
///
93+
/// - It is sometimes provided as a "magic" value, for example, -1. This
94+
/// value is undocumented and not standard, but it is often used to represent
95+
/// the largest possible backlog size. This happens due to signed/unsigned
96+
/// conversion and rounding to the upper bound performed by the OS.
97+
///
98+
/// - Default values vary depending on the OS and its version. Common defaults
99+
/// include: -1, 128, 1024, and 4096.
100+
///
101+
#[allow(dead_code)]
102+
pub(crate) const fn get_listen_backlog_size() -> i32 {
103+
// Here is the original code from the standard library
104+
// https://github.com/rust-lang/rust/blob/4f808ba6bf9f1c8dde30d009e73386d984491587/library/std/src/os/unix/net/listener.rs#L72
105+
#[cfg(any(
106+
target_os = "windows",
107+
target_os = "redox",
108+
target_os = "espidf",
109+
target_os = "horizon"
110+
))]
111+
const BACKLOG_SIZE: i32 = 128;
112+
113+
#[allow(dead_code)]
114+
#[cfg(any(
115+
// Silently capped to `/proc/sys/net/core/somaxconn`.
116+
target_os = "linux",
117+
// Silently capped to `kern.ipc.soacceptqueue`.
118+
target_os = "freebsd",
119+
// Silently capped to `kern.somaxconn sysctl`.
120+
target_os = "openbsd",
121+
// Silently capped to the default 128.
122+
target_vendor = "apple",
123+
))]
124+
const BACKLOG_SIZE: i32 = -1;
125+
126+
#[allow(dead_code)]
127+
#[cfg(not(any(
128+
target_os = "windows",
129+
target_os = "redox",
130+
target_os = "espidf",
131+
target_os = "horizon",
132+
target_os = "linux",
133+
target_os = "freebsd",
134+
target_os = "openbsd",
135+
target_vendor = "apple",
136+
)))]
137+
const BACKLOG_SIZE: i32 = libc::SOMAXCONN;
138+
BACKLOG_SIZE
139+
}

src/sys/shell/tcp.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub(crate) fn connect(_: &net::TcpStream, _: SocketAddr) -> io::Result<()> {
1717
}
1818

1919
#[cfg(not(target_os = "wasi"))]
20-
pub(crate) fn listen(_: &net::TcpListener, _: u32) -> io::Result<()> {
20+
pub(crate) fn listen(_: &net::TcpListener, _: i32) -> io::Result<()> {
2121
os_required!();
2222
}
2323

src/sys/unix/tcp.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use std::convert::TryInto;
21
use std::io;
32
use std::mem::{size_of, MaybeUninit};
43
use std::net::{self, SocketAddr};
@@ -38,8 +37,7 @@ pub(crate) fn connect(socket: &net::TcpStream, addr: SocketAddr) -> io::Result<(
3837
}
3938
}
4039

41-
pub(crate) fn listen(socket: &net::TcpListener, backlog: u32) -> io::Result<()> {
42-
let backlog = backlog.try_into().unwrap_or(i32::MAX);
40+
pub(crate) fn listen(socket: &net::TcpListener, backlog: i32) -> io::Result<()> {
4341
syscall!(listen(socket.as_raw_fd(), backlog))?;
4442
Ok(())
4543
}

src/sys/unix/uds/listener.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::path::Path;
66
use std::{io, mem};
77

88
use crate::net::UnixStream;
9+
use crate::sys::get_listen_backlog_size;
910
use crate::sys::unix::net::new_socket;
1011
use crate::sys::unix::uds::{path_offset, unix_addr};
1112

@@ -16,7 +17,7 @@ pub(crate) fn bind_addr(address: &SocketAddr) -> io::Result<net::UnixListener> {
1617
let (unix_address, addrlen) = unix_addr(address);
1718
let sockaddr = &unix_address as *const libc::sockaddr_un as *const libc::sockaddr;
1819
syscall!(bind(fd, sockaddr, addrlen))?;
19-
syscall!(listen(fd, 1024))?;
20+
syscall!(listen(fd, get_listen_backlog_size()))?;
2021

2122
Ok(socket)
2223
}

src/sys/windows/tcp.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,10 @@ pub(crate) fn connect(socket: &net::TcpStream, addr: SocketAddr) -> io::Result<(
4646
}
4747
}
4848

49-
pub(crate) fn listen(socket: &net::TcpListener, backlog: u32) -> io::Result<()> {
49+
pub(crate) fn listen(socket: &net::TcpListener, backlog: i32) -> io::Result<()> {
5050
use std::convert::TryInto;
5151
use WinSock::listen;
5252

53-
let backlog = backlog.try_into().unwrap_or(i32::MAX);
5453
syscall!(
5554
listen(socket.as_raw_socket() as _, backlog),
5655
PartialEq::eq,

0 commit comments

Comments
 (0)