-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Update stream impl for Framed to return None
after Err
#4166
Conversation
Introduce a new terminal state to the `Framed` `Stream` impl which is reached whenever the underlying decoder returns an `Err`. Once we reach this state, we always return `None` when the stream is polled.
I'll be adding tests to this tomorrow. |
tokio-util/src/codec/framed_impl.rs
Outdated
// Return `None` if we have encountered an error from the underlying decoder | ||
// See: https://github.com/tokio-rs/tokio/issues/3976 | ||
if state.has_errored { | ||
return Poll::Ready(None); | ||
} |
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.
Currently the stream is not fused when you reach EOF normally. Maybe we should put it back into the paused
state after returning None
?
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.
I'm not quite sure what that means. If we move to the paused
state, that means that the errored
state is no longer terminal. I thought we wanted to return None
to the stream after the underlying decoder errored out?
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.
Sure, but do we want to keep returning none if they keep trying to read from it? See #3272 for context.
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.
Ah I see what you mean now. Yeah, it makes sense to move it to the paused
state after returning None
.
tokio-util/src/codec/framed_impl.rs
Outdated
// | errored | <any> | <any> | true | `decode_eof` returns Err | ||
// ┌───────────────────────────────────────┐ | ||
// `decode_eof` │ │ | ||
// returns Ok(`Some`) │ read 0 bytes │ | ||
// │ │ ┌───────┘ │ │ │ | ||
// │ ▼ │ │ ▼ │ | ||
// ┌───────────┐ `decode_eof` ┌──────┐ │ | ||
// ┌──read 0 bytes──▶│ pausing │─returns Ok(`None`)─▶│paused│───────┐ │ | ||
// │ └───────────┘ └──────┘ │ ▼ | ||
// pending read┐ │ ┌──────┐ │ ▲ │ ┌─────────┐ | ||
// │ │ │ │ │ │ │ │ │ errored │ | ||
// │ ▼ │ │ `decode` returns `Some` │ pending read └─────────┘ | ||
// │ ╔═══════╗ ┌───────────┐◀─┘ │ ▲ | ||
// └──║reading║─read n>0 bytes─▶│ framing │ │ │ | ||
// ╚═══════╝ └───────────┘◀──────read n>0 bytes┘ │ | ||
// ▲ │ │ │ | ||
// │ │ │ `decode` returns Err │ | ||
// └─`decode` returns `None`──┘ └────────────────────────────────────────────────┘ |
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 picture is kinda broken. I think you need to adjust some spaces to make stuff line up.
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.
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.
You might need to use a different character for the arrows.
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.
The diagram is still pretty broken.
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.
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.
that might indeed be the best way.
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.
Sorry for the late reply, I was traveling over the weekend. I'll push a new revision tonight.
tokio-util/src/codec/framed.rs
Outdated
@@ -106,6 +106,7 @@ where | |||
eof: false, | |||
is_readable: false, | |||
buffer: BytesMut::with_capacity(capacity), | |||
has_errored: false |
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.
There are some rustfmt failures:
Diff in /home/runner/work/tokio/tokio/tokio-util/src/codec/framed.rs at line 106:
eof: false,
is_readable: false,
buffer: BytesMut::with_capacity(capacity),
- has_errored: false
+ has_errored: false,
},
write: WriteFrame::default(),
},
Diff in /home/runner/work/tokio/tokio/tokio-util/src/codec/framed_read.rs at line 51:
eof: false,
is_readable: false,
buffer: BytesMut::with_capacity(capacity),
- has_errored: false
+ has_errored: false,
},
},
}
Diff in /home/runner/work/tokio/tokio/tokio-util/src/codec/framed.rs at line 106:
eof: false,
is_readable: false,
buffer: BytesMut::with_capacity(capacity),
- has_errored: false
+ has_errored: false,
},
write: WriteFrame::default(),
},
Diff in /home/runner/work/tokio/tokio/tokio-util/src/codec/framed_read.rs at line 51:
eof: false,
is_readable: false,
buffer: BytesMut::with_capacity(capacity),
- has_errored: false
+ has_errored: false,
},
},
}
You can fix them by running
rustfmt --edition 2018 $(git ls-files '*.rs')
Something I'd like to do as an improvement would be to refactor the stream state ( |
If you want to refactor it, that's fine with me. |
I'll do the refactor as a separate PR. |
tokio-util/tests/framed_stream.rs
Outdated
// ================= Mock ================= | ||
struct Mock { | ||
calls: VecDeque<io::Result<Vec<u8>>>, | ||
} |
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.
Is there any reason you aren't using the mock in tokio-test
?
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.
I followed the pattern in the other codec tests mostly. I saw that there's a lot of duplication, but didn't know about tokio-test
itself. Do you want me to move this test to use tokio-test
?
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.
I think it would be cleaner to use tokio-test
.
Not entirely sure why the bsd tests are failing. |
You might need to merge in master to get #4189. |
Please note this change has been breaking for the Basically, |
We could revert. There are other changes pending for an 0.7 anyway. Maybe you could join our discord so we can discuss? |
Well, I was able to fix it in the I guess we could wait it out and see if anyone else shows up? 🤷 |
Just for posterity, we were likewise bitten by this change in Vector: vectordotdev/vector#11254 . Our |
Motivation
Decoder::decode()
says an Err informsFramed
that the stream should be terminated, butFramed
doesn't terminate #3976Solution
Introduce a new terminal state to the
Framed
Stream
impl which isreached whenever the underlying decoder returns an
Err
. Once we reachthis state, we always return
None
when the stream is polled.