From 74a5e072fefe9e27743a181e63847e00501d804e Mon Sep 17 00:00:00 2001 From: "Arvid E. Picciani" Date: Sat, 16 Jun 2018 01:04:13 +0200 Subject: [PATCH] Fix tight loop on aborted connection (#285) When the underlying IO returns 0 on read, we must stop polling it since it's closed. Otherwise we'll be stuck in a tight loop. this fixes https://github.com/sfackler/rust-openssl/issues/949 --- src/server.rs | 8 +++++++- tests/h2-support/src/mock.rs | 2 +- tests/h2-tests/tests/server.rs | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/server.rs b/src/server.rs index 799b3e4..bd2185c 100644 --- a/src/server.rs +++ b/src/server.rs @@ -140,7 +140,7 @@ use proto::{self, Config, Prioritized}; use bytes::{Buf, Bytes, IntoBuf}; use futures::{self, Async, Future, Poll}; use http::{Request, Response}; -use std::{convert, fmt, mem}; +use std::{convert, fmt, io, mem}; use std::time::Duration; use tokio_io::{AsyncRead, AsyncWrite}; @@ -1045,6 +1045,12 @@ where while rem > 0 { let n = try_nb!(self.inner_mut().read(&mut buf[..rem])); + if n == 0 { + return Err(io::Error::new( + io::ErrorKind::ConnectionReset, + "connection closed unexpectedly", + ).into()); + } if PREFACE[self.pos..self.pos + n] != buf[..n] { // TODO: Should this just write the GO_AWAY frame directly? diff --git a/tests/h2-support/src/mock.rs b/tests/h2-support/src/mock.rs index d1ae3d0..ee81980 100644 --- a/tests/h2-support/src/mock.rs +++ b/tests/h2-support/src/mock.rs @@ -329,7 +329,7 @@ impl io::Write for Mock { let mut me = self.pipe.inner.lock().unwrap(); if me.closed { - return Err(io::Error::new(io::ErrorKind::BrokenPipe, "mock closed")); + return Ok(buf.len()); } if me.tx_rem == 0 { diff --git a/tests/h2-tests/tests/server.rs b/tests/h2-tests/tests/server.rs index 55a8fa2..1bbec43 100644 --- a/tests/h2-tests/tests/server.rs +++ b/tests/h2-tests/tests/server.rs @@ -589,3 +589,19 @@ fn poll_reset_after_send_response_is_user_error() { srv.join(client).wait().expect("wait"); } + +#[test] +fn server_error_on_unclean_shutdown() { + use std::io::Write; + + let _ = ::env_logger::try_init(); + let (io, mut client) = mock::new(); + + let srv = server::Builder::new() + .handshake::<_, Bytes>(io); + + client.write_all(b"PRI *").expect("write"); + drop(client); + + srv.wait().expect_err("should error"); +}