diff --git a/tokio/src/net/tcp/socket.rs b/tokio/src/net/tcp/socket.rs index eb3ea5109..e941c5c3a 100644 --- a/tokio/src/net/tcp/socket.rs +++ b/tokio/src/net/tcp/socket.rs @@ -419,6 +419,17 @@ impl TcpSocket { /// /// If `SO_LINGER` is not specified, and the socket is closed, the system handles the call in a /// way that allows the process to continue as quickly as possible. + /// + /// This option is deprecated because setting `SO_LINGER` on a socket used with Tokio is always + /// incorrect as it leads to blocking the thread when the socket is closed. For more details, + /// please see: + /// + /// > Volumes of communications have been devoted to the intricacies of `SO_LINGER` versus + /// > non-blocking (`O_NONBLOCK`) sockets. From what I can tell, the final word is: don't do + /// > it. Rely on the `shutdown()`-followed-by-`read()`-eof technique instead. + /// > + /// > From [The ultimate `SO_LINGER` page, or: why is my tcp not reliable](https://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable) + #[deprecated = "`SO_LINGER` causes the socket to block the thread on drop"] pub fn set_linger(&self, dur: Option) -> io::Result<()> { self.inner.set_linger(dur) } diff --git a/tokio/src/net/tcp/stream.rs b/tokio/src/net/tcp/stream.rs index 8d8127ffd..c432b3f43 100644 --- a/tokio/src/net/tcp/stream.rs +++ b/tokio/src/net/tcp/stream.rs @@ -1278,9 +1278,20 @@ impl TcpStream { /// If `SO_LINGER` is not specified, and the stream is closed, the system handles the call in a /// way that allows the process to continue as quickly as possible. /// + /// This option is deprecated because setting `SO_LINGER` on a socket used with Tokio is + /// always incorrect as it leads to blocking the thread when the socket is closed. For more + /// details, please see: + /// + /// > Volumes of communications have been devoted to the intricacies of `SO_LINGER` versus + /// > non-blocking (`O_NONBLOCK`) sockets. From what I can tell, the final word is: don't + /// > do it. Rely on the `shutdown()`-followed-by-`read()`-eof technique instead. + /// > + /// > From [The ultimate `SO_LINGER` page, or: why is my tcp not reliable](https://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable) + /// /// # Examples /// /// ```no_run + /// # #![allow(deprecated)] /// use tokio::net::TcpStream; /// /// # async fn dox() -> Result<(), Box> { @@ -1290,6 +1301,7 @@ impl TcpStream { /// # Ok(()) /// # } /// ``` + #[deprecated = "`SO_LINGER` causes the socket to block the thread on drop"] pub fn set_linger(&self, dur: Option) -> io::Result<()> { socket2::SockRef::from(self).set_linger(dur) } diff --git a/tokio/tests/tcp_connect.rs b/tokio/tests/tcp_connect.rs index feaf703ed..d3638701e 100644 --- a/tokio/tests/tcp_connect.rs +++ b/tokio/tests/tcp_connect.rs @@ -181,6 +181,7 @@ mod linux { use std::{net, thread}; #[tokio::test] + #[expect(deprecated)] // set_linger is deprecated fn poll_hup() { let addr = assert_ok!("127.0.0.1:0".parse()); let mut srv = assert_ok!(TcpListener::bind(&addr)); diff --git a/tokio/tests/tcp_shutdown.rs b/tokio/tests/tcp_shutdown.rs index 837e61230..130b07913 100644 --- a/tokio/tests/tcp_shutdown.rs +++ b/tokio/tests/tcp_shutdown.rs @@ -33,6 +33,7 @@ async fn shutdown() { } #[tokio::test] +#[expect(deprecated)] // set_linger is deprecated async fn shutdown_after_tcp_reset() { let srv = assert_ok!(TcpListener::bind("127.0.0.1:0").await); let addr = assert_ok!(srv.local_addr()); diff --git a/tokio/tests/tcp_socket.rs b/tokio/tests/tcp_socket.rs index c05dc1f53..8c01b86e4 100644 --- a/tokio/tests/tcp_socket.rs +++ b/tokio/tests/tcp_socket.rs @@ -62,6 +62,7 @@ async fn bind_before_connect() { } #[tokio::test] +#[expect(deprecated)] // set_linger is deprecated async fn basic_linger() { // Create server let addr = assert_ok!("127.0.0.1:0".parse()); diff --git a/tokio/tests/tcp_stream.rs b/tokio/tests/tcp_stream.rs index 1352f5344..c565b9af5 100644 --- a/tokio/tests/tcp_stream.rs +++ b/tokio/tests/tcp_stream.rs @@ -14,6 +14,7 @@ use std::time::Duration; #[tokio::test] #[cfg_attr(miri, ignore)] // No `socket` on miri. +#[expect(deprecated)] // set_linger is deprecated async fn set_linger() { let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();