///
/// 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)
}
/// 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>> {
/// # 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)
}
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));
}
#[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());
}
#[tokio::test]
+#[expect(deprecated)] // set_linger is deprecated
async fn basic_linger() {
// Create server
let addr = assert_ok!("127.0.0.1:0".parse());
#[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();