Avoid prematurely unlinking streams in send_reset, in some cases. (#319)
Because `send_reset` called `recv_err`, which calls `reclaim_all_capacity`, which eventually calls `transition(stream, ..)` -- all of which happens _before_ the RESET frame is enqueued -- it was possible for the stream to get unlinked from the store (if there was any connection-level capacity to reassign). This could then cause the stream to get "leaked" on drop/EOF since it would no longer be iterated. Fix this by delaying the call to `reclaim_all_capacity` _after_ enqueueing the RESET frame. A test demonstrating the issue is included.
This commit is contained in:
committed by
Carl Lerche
parent
9bbbe7ebd5
commit
ea8b8ac2fd
@@ -159,12 +159,17 @@ impl Send {
|
||||
return;
|
||||
}
|
||||
|
||||
self.recv_err(buffer, stream, counts);
|
||||
// Clear all pending outbound frames.
|
||||
// Note that we don't call `self.recv_err` because we want to enqueue
|
||||
// the reset frame before transitioning the stream inside
|
||||
// `reclaim_all_capacity`.
|
||||
self.prioritize.clear_queue(buffer, stream);
|
||||
|
||||
let frame = frame::Reset::new(stream.id, reason);
|
||||
|
||||
trace!("send_reset -- queueing; frame={:?}", frame);
|
||||
self.prioritize.queue_frame(frame.into(), buffer, stream, task);
|
||||
self.prioritize.reclaim_all_capacity(stream, counts);
|
||||
}
|
||||
|
||||
pub fn schedule_implicit_reset(
|
||||
|
||||
Reference in New Issue
Block a user