Skip to content

Commit 8f7b87c

Browse files
authored
Use same backlog argument as std in listen calls (#1896)
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.
1 parent 8e5a4b5 commit 8f7b87c

File tree

6 files changed

+75
-10
lines changed

6 files changed

+75
-10
lines changed

src/net/tcp/listener.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ use crate::net::TcpStream;
1616
#[cfg(any(unix, target_os = "hermit"))]
1717
use crate::sys::tcp::set_reuseaddr;
1818
#[cfg(not(target_os = "wasi"))]
19-
use crate::sys::tcp::{bind, listen, new_for_addr};
19+
use crate::sys::{
20+
tcp::{bind, listen, new_for_addr},
21+
LISTEN_BACKLOG_SIZE,
22+
};
2023
use crate::{event, sys, Interest, Registry, Token};
2124

2225
/// A structure representing a socket server
@@ -78,7 +81,7 @@ impl TcpListener {
7881
set_reuseaddr(&listener.inner, true)?;
7982

8083
bind(&listener.inner, addr)?;
81-
listen(&listener.inner, 1024)?;
84+
listen(&listener.inner, LISTEN_BACKLOG_SIZE)?;
8285
Ok(listener)
8386
}
8487

src/sys/mod.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,68 @@ 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+
// Here is the original code from the standard library
102+
// https://github.com/rust-lang/rust/blob/4f808ba6bf9f1c8dde30d009e73386d984491587/library/std/src/os/unix/net/listener.rs#L72
103+
//
104+
#[allow(dead_code)]
105+
#[cfg(any(
106+
target_os = "windows",
107+
target_os = "redox",
108+
target_os = "espidf",
109+
target_os = "horizon"
110+
))]
111+
pub(crate) const LISTEN_BACKLOG_SIZE: i32 = 128;
112+
113+
/// This is a special case for some target(s) supported by `mio`. This value
114+
/// is needed because `libc::SOMAXCON` (used as a fallback for unknown targets)
115+
/// is not implemented for them. Feel free to update this if the `libc` crate
116+
/// changes.
117+
#[allow(dead_code)]
118+
#[cfg(target_os = "hermit")]
119+
pub(crate) const LISTEN_BACKLOG_SIZE: i32 = 1024;
120+
121+
#[allow(dead_code)]
122+
#[cfg(any(
123+
// Silently capped to `/proc/sys/net/core/somaxconn`.
124+
target_os = "linux",
125+
// Silently capped to `kern.ipc.soacceptqueue`.
126+
target_os = "freebsd",
127+
// Silently capped to `kern.somaxconn sysctl`.
128+
target_os = "openbsd",
129+
// Silently capped to the default 128.
130+
target_vendor = "apple",
131+
))]
132+
pub(crate) const LISTEN_BACKLOG_SIZE: i32 = -1;
133+
134+
#[allow(dead_code)]
135+
#[cfg(not(any(
136+
target_os = "windows",
137+
target_os = "redox",
138+
target_os = "espidf",
139+
target_os = "horizon",
140+
target_os = "linux",
141+
target_os = "freebsd",
142+
target_os = "openbsd",
143+
target_os = "wasi",
144+
target_os = "hermit",
145+
target_vendor = "apple",
146+
)))]
147+
pub(crate) const LISTEN_BACKLOG_SIZE: i32 = libc::SOMAXCONN;

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
@@ -8,6 +8,7 @@ use std::{io, mem};
88
use crate::net::UnixStream;
99
use crate::sys::unix::net::new_socket;
1010
use crate::sys::unix::uds::{path_offset, unix_addr};
11+
use crate::sys::LISTEN_BACKLOG_SIZE;
1112

1213
pub(crate) fn bind_addr(address: &SocketAddr) -> io::Result<net::UnixListener> {
1314
let fd = new_socket(libc::AF_UNIX, libc::SOCK_STREAM)?;
@@ -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, LISTEN_BACKLOG_SIZE))?;
2021

2122
Ok(socket)
2223
}

src/sys/windows/tcp.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,9 @@ 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<()> {
50-
use std::convert::TryInto;
49+
pub(crate) fn listen(socket: &net::TcpListener, backlog: i32) -> io::Result<()> {
5150
use WinSock::listen;
5251

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

0 commit comments

Comments
 (0)