-
Notifications
You must be signed in to change notification settings - Fork 949
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
Decoding occasionally fails when streaming #76
Comments
After making the following changes I'm now unable to reproduce the issue: diff --git a/tonic/src/codec/prost.rs b/tonic/src/codec/prost.rs
index 495dc11..5c29a06 100644
--- a/tonic/src/codec/prost.rs
+++ b/tonic/src/codec/prost.rs
@@ -49,12 +49,14 @@ impl<T: Message> Encoder for ProstEncoder<T> {
fn encode(&mut self, item: Self::Item, buf: &mut BytesMut) -> Result<(), Self::Error> {
let len = item.encoded_len();
+ let additional = prost::encoding::encoded_len_varint(len as u64);
+ let required = len + additional;
- if buf.remaining_mut() < len {
- buf.reserve(len);
+ if buf.remaining_mut() < required {
+ buf.reserve(required);
}
- item.encode(buf)
+ item.encode_length_delimited(buf)
.map_err(|_| unreachable!("Message only errors if not enough space"))
}
}
@@ -68,7 +70,7 @@ impl<U: Message + Default> Decoder for ProstDecoder<U> {
type Error = Status;
fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
- Message::decode(buf.take())
+ Message::decode_length_delimited(buf.take())
.map(Option::Some)
.map_err(from_decode_error)
} However, I'm not exactly sure how to reliably test that this changes solves the problem. |
I think I was running a client without the above changes against a server with the changes, which yields the same behavior. |
I'm still able to reproduce this in my specific application, so the patch above isn't a fix. |
I can reproduce with |
@seanmonstar would hyper be cutting the body off by chance? |
I wouldn't expect it to. Could try wireshark or something to sniff what |
Cool I'll look at it with Wireshark. |
Looking at the logs coming out of Is there any reason the decoder would not wait for at minimum the number of bytes required to fully decode a message? |
@seanmonstar After looking at frames using wireshark, I don't see anything anomalous. 10005 bytes are sent as I noticed that between the 10005 bytes being sent the tonic decoding thread gets woken up and tries to decode the message before having all the bytes needed to decode it. |
I'm not convinced this is related to threading or h2. I think that the issue most likely lies in tonic. When receiving data by polling the body, it's possible to end up in a situation where the polling results in a buffer of size Roughly the flow is like this:
|
Bug Report
Version
Running from 1987a40.
Platform
Crates
Affects
tonic
Description
When running these lines I occasionally get an error message from
prost
informing me that a buffer underflow has occurred:Sometimes this happens, other times it doesn't. It seems to be related to the number of bytes that I try to push through from the server to the client.
After digging around for quite some time, the failing requests all seem to be missing 3 additional bytes after the 5 byte header. When testing the
blob-client
with10000
bytes a request ends up having a total length of10005
. After the buffer is advanced 5 bytes, the length is now10000
. Theprost::encoding::bytes::merge
function then reads off 3 bytes to get the length of the byte array from the proto, which is10000
and then checks for underflow.I'm stumped as to how these bytes are missing in some cases and are present in many others.
This prost issue (https://github.com/danburkert/prost/issues/98) suggests using
{encode|decode}_length_delimited
, but that didn't seem to have any effect when I swapped those calls in inprost.rs
.The text was updated successfully, but these errors were encountered: