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
This commit is contained in:
committed by
Carl Lerche
parent
2b59803866
commit
74a5e072fe
@@ -140,7 +140,7 @@ use proto::{self, Config, Prioritized};
|
|||||||
use bytes::{Buf, Bytes, IntoBuf};
|
use bytes::{Buf, Bytes, IntoBuf};
|
||||||
use futures::{self, Async, Future, Poll};
|
use futures::{self, Async, Future, Poll};
|
||||||
use http::{Request, Response};
|
use http::{Request, Response};
|
||||||
use std::{convert, fmt, mem};
|
use std::{convert, fmt, io, mem};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
|
|
||||||
@@ -1045,6 +1045,12 @@ where
|
|||||||
|
|
||||||
while rem > 0 {
|
while rem > 0 {
|
||||||
let n = try_nb!(self.inner_mut().read(&mut buf[..rem]));
|
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] {
|
if PREFACE[self.pos..self.pos + n] != buf[..n] {
|
||||||
// TODO: Should this just write the GO_AWAY frame directly?
|
// TODO: Should this just write the GO_AWAY frame directly?
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ impl io::Write for Mock {
|
|||||||
let mut me = self.pipe.inner.lock().unwrap();
|
let mut me = self.pipe.inner.lock().unwrap();
|
||||||
|
|
||||||
if me.closed {
|
if me.closed {
|
||||||
return Err(io::Error::new(io::ErrorKind::BrokenPipe, "mock closed"));
|
return Ok(buf.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
if me.tx_rem == 0 {
|
if me.tx_rem == 0 {
|
||||||
|
|||||||
@@ -589,3 +589,19 @@ fn poll_reset_after_send_response_is_user_error() {
|
|||||||
|
|
||||||
srv.join(client).wait().expect("wait");
|
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");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user