-
-
Notifications
You must be signed in to change notification settings - Fork 291
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reset any queued stream on receipt of remote reset #258
Conversation
src/proto/streams/state.rs
Outdated
@@ -217,10 +217,11 @@ impl State { | |||
pub fn recv_reset(&mut self, reason: Reason, queued: bool) { | |||
|
|||
match self.inner { | |||
Closed(Cause::EndStream) if queued => { | |||
Closed(prior_reason) if queued => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks like the only functional change in this PR... can you explain how this resolves the issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. It would be good to include a comment explaining this as it is definitely subtle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, the match can be condensed as:
pub fn recv_reset(&mut self, reason: Reason, queued: bool) {
match self.inner {
Closed(..) if !queued => {},
s => {
trace!("recv_reset; reason={:?}; state={:?}", reason, s);
self.inner = Closed(Cause::Proto(reason));
}
}
}
I want to make sure I understand this properly, though. What are the states where we can be closed and have queued data?
In particular, I'm not sure if it makes sense to change the closed type when it's already Proto
(it's probably harmless? but I'm not sure of the intended behavior). Also, I'm not sure we'd want to override an Io
error (though I'm not sure if it's actually possible to receive a reset after an Io error).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fair, I can make the match more specific.
My understanding is that we can have queued data in the following cases:
- when the cause
Cause::Scheduled
, - when the cause is
Cause::EndStream
, which would indicate that we've enqueued an EOS frame but it has yet to be sent (either because there are other frames ahead of it in the send queue, or we just haven't popped it yet)
AFAIK, queued
should not be true with any other Cause
variants, but I'll change the pattern match to actually encode this nonetheless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/proto/streams/state.rs
Outdated
// | ||
// In either of these cases, we want to honor the received | ||
// RST_STREAM by resetting the stream immediately (and clearing | ||
// the send queue). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't clear the sendq here. Would be clearer as:
... immediately. This causes the send queue to be cleared by
prioritize
.
(Or whatever is actually correct.
Hm, there's one more way that we can call |
@goffrie Ah, thanks for pointing that out --- I think we'll want to add similar logic to |
Thanks for getting this done. |
Fixes #256.
This PR changes
state::recv_reset
so any closed stream with queued send is immediately reset (and thus, the queue is cleared) on receipt of aRST_STREAM
frame from the remote.This fixes the panic encountered by the test @goffrie posted in #256, where the stream is scheduled to close, receives a
RST_STREAM
frame, and sets the buffered capacity to 0, but isn't removed from the send queue, so we hit an assertion (or overflow, if debug assertions are disabled) when subtracting a sent frame's size from the buffered size.I've determined that this does fix the panic in @goffrie's test, but the test instead hangs forever instead of passing. I haven't yet been able to rewrite the test such that it hits the panic on master but doesn't hang when the issue is resolved. I intend to continue working on testing this, but I'm putting this up for review now nonetheless.