Release closed streams capacity back to connection (#334)

Previously, any streams that were dropped or closed while not having
consumed the inflight received window capacity would simply leak that
capacity for the connection. This could easily happen if a `RecvStream`
were dropped before fully consuming the data, and therefore a user would
have no idea how much capacity to release in the first place. This
resulted in stalled connections that would never have capacity again.
This commit is contained in:
Sean McArthur
2018-12-05 09:44:20 -08:00
committed by GitHub
parent 545ff1e7dd
commit c7d4182ffe
3 changed files with 110 additions and 19 deletions

View File

@@ -334,7 +334,11 @@ impl Recv {
capacity: WindowSize,
task: &mut Option<Task>,
) {
trace!("release_connection_capacity; size={}", capacity);
trace!(
"release_connection_capacity; size={}, connection in_flight_data={}",
capacity,
self.in_flight_data,
);
// Decrement in-flight data
self.in_flight_data -= capacity;
@@ -383,6 +387,31 @@ impl Recv {
Ok(())
}
/// Release any unclaimed capacity for a closed stream.
pub fn release_closed_capacity(
&mut self,
stream: &mut store::Ptr,
task: &mut Option<Task>,
) {
debug_assert_eq!(stream.ref_count, 0);
if stream.in_flight_recv_data == 0 {
return;
}
trace!(
"auto-release closed stream ({:?}) capacity: {:?}",
stream.id,
stream.in_flight_recv_data,
);
self.release_connection_capacity(
stream.in_flight_recv_data,
task,
);
stream.in_flight_recv_data = 0;
}
/// Set the "target" connection window size.
///
/// By default, all new connections start with 64kb of window size. As
@@ -515,12 +544,6 @@ impl Recv {
});
}
// Update stream level flow control
stream.recv_flow.send_data(sz);
// Track the data as in-flight
stream.in_flight_recv_data += sz;
if stream.dec_content_length(frame.payload().len()).is_err() {
trace!("content-length overflow");
return Err(RecvError::Stream {
@@ -544,6 +567,12 @@ impl Recv {
}
}
// Update stream level flow control
stream.recv_flow.send_data(sz);
// Track the data as in-flight
stream.in_flight_recv_data += sz;
let event = Event::Data(frame.into_payload());
// Push the frame onto the recv buffer