From 12028cc418f1b82ce2f7fec5cf63d1c609815198 Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Wed, 8 Aug 2018 15:43:47 -0700 Subject: [PATCH] fix panic when calling reserve_capacity after connection closes (#302) --- src/proto/streams/prioritize.rs | 8 +++++- tests/h2-tests/tests/flow_control.rs | 39 ++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/proto/streams/prioritize.rs b/src/proto/streams/prioritize.rs index b1d59fc..6e509b1 100644 --- a/src/proto/streams/prioritize.rs +++ b/src/proto/streams/prioritize.rs @@ -225,7 +225,7 @@ impl Prioritize { ); // Actual capacity is `capacity` + the current amount of buffered data. - // It it were less, then we could never send out the buffered data. + // If it were less, then we could never send out the buffered data. let capacity = capacity + stream.buffered_send_data; if capacity == stream.requested_send_capacity { @@ -247,6 +247,12 @@ impl Prioritize { self.assign_connection_capacity(diff, stream, counts); } } else { + // If trying to *add* capacity, but the stream send side is closed, + // there's nothing to be done. + if stream.state.is_send_closed() { + return; + } + // Update the target requested capacity stream.requested_send_capacity = capacity; diff --git a/tests/h2-tests/tests/flow_control.rs b/tests/h2-tests/tests/flow_control.rs index 5943781..c102994 100644 --- a/tests/h2-tests/tests/flow_control.rs +++ b/tests/h2-tests/tests/flow_control.rs @@ -1259,3 +1259,42 @@ fn recv_settings_increase_window_size_after_using_some() { srv.join(client).wait().unwrap(); } + +#[test] +fn reserve_capacity_after_peer_closes() { + // See https://github.com/carllerche/h2/issues/300 + let _ = ::env_logger::try_init(); + let (io, srv) = mock::new(); + + let srv = srv.assert_client_handshake() + .unwrap() + .recv_settings() + .recv_frame( + frames::headers(1) + .request("POST", "https://http2.akamai.com/") + ) + // close connection suddenly + .close(); + + let client = client::handshake(io).unwrap() + .and_then(|(mut client, conn)| { + let request = Request::builder() + .method("POST") + .uri("https://http2.akamai.com/") + .body(()).unwrap(); + let (resp, req_body) = client.send_request(request, false).unwrap(); + conn.drive(resp.then(move |result| { + assert!(result.is_err()); + Ok::<_, ()>(req_body) + })) + }) + .and_then(|(conn, mut req_body)| { + // As stated in #300, this would panic because the connection + // had already been closed. + req_body.reserve_capacity(1); + conn.expect("client") + }); + + srv.join(client).wait().expect("wait"); +} +