]> git.feebdaed.xyz Git - 0xmirror/tokio.git/commitdiff
net: deprecate `{TcpStream,TcpSocket}::set_linger` (#7752)
authorAlice Ryhl <aliceryhl@google.com>
Tue, 2 Dec 2025 12:15:48 +0000 (13:15 +0100)
committerGitHub <noreply@github.com>
Tue, 2 Dec 2025 12:15:48 +0000 (13:15 +0100)
tokio/src/net/tcp/socket.rs
tokio/src/net/tcp/stream.rs
tokio/tests/tcp_connect.rs
tokio/tests/tcp_shutdown.rs
tokio/tests/tcp_socket.rs
tokio/tests/tcp_stream.rs

index eb3ea510923aec5b4e3987875f375b6adc532bad..e941c5c3a8252b04dcf825527fb39d33faff4535 100644 (file)
@@ -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<Duration>) -> io::Result<()> {
         self.inner.set_linger(dur)
     }
index 8d8127ffd865320adeccd5f12c01df9617517008..c432b3f43702907f6fca868fd3ccfc18212ce8b2 100644 (file)
@@ -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<dyn std::error::Error>> {
@@ -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<Duration>) -> io::Result<()> {
             socket2::SockRef::from(self).set_linger(dur)
         }
index feaf703ededdca27e3c52809965a3681b37494d4..d3638701eb5d69da7d3055424b384a53b95b9388 100644 (file)
@@ -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));
index 837e6123053b4ff3a6648180d072578da190e373..130b079131d68721d8564e568467e683c68ebaa5 100644 (file)
@@ -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());
index c05dc1f5319805c100ff1e1650a04e7185e33188..8c01b86e4a1680b3749047bd0395a472a7d8e69c 100644 (file)
@@ -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());
index 1352f5344055acd16b8425081d5156700a3dd5ea..c565b9af5066b19c1f367c3e85e845b2cb99f686 100644 (file)
@@ -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();