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"); +}