mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-07 00:00:09 +02:00
net: fix OwnedWriteHalf behavior on drop (#2597)
Previously, dropping the Write handle would issue a `shutdown(Both)`. However, shutting down the read half is not portable and not the correct action to take. This changes the behavior of OwnedWriteHalf to only perform a `shutdown(Write)` on drop.
This commit is contained in:
@@ -40,7 +40,7 @@ pub struct OwnedReadHalf {
|
||||
/// Note that in the [`AsyncWrite`] implemenation of this type, [`poll_shutdown`] will
|
||||
/// shut down the TCP stream in the write direction.
|
||||
///
|
||||
/// Dropping the write half will close the TCP stream in both directions.
|
||||
/// Dropping the write half will shutdown the write half of the TCP stream.
|
||||
///
|
||||
/// Writing to an `OwnedWriteHalf` is usually done using the convenience methods found
|
||||
/// on the [`AsyncWriteExt`] trait. Examples import this trait through [the prelude].
|
||||
@@ -209,9 +209,8 @@ impl OwnedWriteHalf {
|
||||
pub fn reunite(self, other: OwnedReadHalf) -> Result<TcpStream, ReuniteError> {
|
||||
reunite(other, self)
|
||||
}
|
||||
/// Destroy the write half, but don't close the stream until the read half
|
||||
/// is dropped. If the read half has already been dropped, this closes the
|
||||
/// stream.
|
||||
|
||||
/// Drop the write half, but don't issue a TCP shutdown.
|
||||
pub fn forget(mut self) {
|
||||
self.shutdown_on_drop = false;
|
||||
drop(self);
|
||||
@@ -221,7 +220,7 @@ impl OwnedWriteHalf {
|
||||
impl Drop for OwnedWriteHalf {
|
||||
fn drop(&mut self) {
|
||||
if self.shutdown_on_drop {
|
||||
let _ = self.inner.shutdown(Shutdown::Both);
|
||||
let _ = self.inner.shutdown(Shutdown::Write);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -652,7 +652,8 @@ impl TcpStream {
|
||||
/// Unlike [`split`], the owned halves can be moved to separate tasks, however
|
||||
/// this comes at the cost of a heap allocation.
|
||||
///
|
||||
/// **Note:** Dropping the write half will close the TCP stream in both directions.
|
||||
/// **Note::** Dropping the write half will shutdown the write half of the TCP
|
||||
/// stream. This is equivalent to calling `shutdown(Write)` on the `TcpStream`.
|
||||
///
|
||||
/// [`split`]: TcpStream::split()
|
||||
pub fn into_split(self) -> (OwnedReadHalf, OwnedWriteHalf) {
|
||||
|
||||
@@ -601,6 +601,19 @@ rt_test! {
|
||||
}
|
||||
|
||||
#[test]
|
||||
// IOCP requires setting the "max thread" concurrency value. The sane,
|
||||
// default, is to set this to the number of cores. Threads that poll I/O
|
||||
// become associated with the IOCP handle. Once those threads sleep for any
|
||||
// reason (mutex), they yield their ownership.
|
||||
//
|
||||
// This test hits an edge case on windows where more threads than cores are
|
||||
// created, none of those threads ever yield due to being at capacity, so
|
||||
// IOCP gets "starved".
|
||||
//
|
||||
// For now, this is a very edge case that is probably not a real production
|
||||
// concern. There also isn't a great/obvious solution to take. For now, the
|
||||
// test is disabled.
|
||||
#[cfg(not(windows))]
|
||||
fn io_driver_called_when_under_load() {
|
||||
let mut rt = rt();
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
use std::io::{Error, ErrorKind, Result};
|
||||
use std::io::{Read, Write};
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::{net, thread};
|
||||
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
@@ -89,9 +88,6 @@ async fn drop_write() -> Result<()> {
|
||||
let listener = net::TcpListener::bind("127.0.0.1:0")?;
|
||||
let addr = listener.local_addr()?;
|
||||
|
||||
let barrier = Arc::new(Barrier::new(2));
|
||||
let barrier2 = barrier.clone();
|
||||
|
||||
let handle = thread::spawn(move || {
|
||||
let (mut stream, _) = listener.accept().unwrap();
|
||||
stream.write_all(MSG).unwrap();
|
||||
@@ -106,8 +102,6 @@ async fn drop_write() -> Result<()> {
|
||||
Err(err) => Err(err),
|
||||
};
|
||||
|
||||
barrier2.wait();
|
||||
|
||||
drop(stream);
|
||||
|
||||
res
|
||||
@@ -132,8 +126,6 @@ async fn drop_write() -> Result<()> {
|
||||
Err(err) => panic!("Unexpected error: {}.", err),
|
||||
}
|
||||
|
||||
barrier.wait();
|
||||
|
||||
handle.join().unwrap().unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user