-
-
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
Seems like read_until
can miss the delimiter byte from time to time
#4908
Comments
Have you tried this? let len = stream
.reader
.read_until(b'\0', &mut stream.read_buffer)
.await
.unwrap();
if len == 0 {
log::warn!(
"Disconnected from {camera_address}...",
camera_address = self.camera_id.addr
);
self.establish_connection().await;
return;
}
// Temp error checking ------------------------------------------------
-if has_null_byte(&stream.read_buffer[..(stream.read_buffer.len() - 1)]) {
+if has_null_byte(&stream.read_buffer[..len]) {
log::error!("BAD XML");
log::info!("buf len: {}", len);
log::info!("vec len: {}", stream.read_buffer.len());
let mut file = tokio::fs::File::create("/home/bpe/BAD_XML.xml")
.await
.unwrap();
file.write_all(&stream.read_buffer[..]).await.unwrap();
}
// --------------------------------------------------------------------- |
Actually, giving this another look, I am more worried about the fact that the call to |
Thx for looking into it. Wow you're fast. I was just answering your comment and it's already updated. Thx again. |
I applied your suggestion, but that caused broken messages again, but with the end part. So I finally figured out that the whole problem is that I didn't really understand how
If the "send command to camera" branch is driven to completion first then the the "receive message from camera" branch is cancelled at a non-deterministic point, then in the next iteration of the loop it reruns the whole future. So this was the cause of the problem in both cases:
So the solution to this was to have the Thank you very much for the help. |
Closing since this appears to be due to incorrect use of |
Version
List the versions of all
tokio
crates you are using. The easiest way to getthis information is using
cargo tree
subcommand: v.1.17.0cargo tree | grep tokio
│ │ ├── tokio v1.17.0
│ │ │ └── tokio-macros v1.7.0 (proc-macro)
│ ├── tokio v1.17.0 ()
│ │ ├── tokio v1.17.0 ()
│ │ ├── tokio-util v0.7.0
│ │ │ └── tokio v1.17.0 ()
│ │ ├── tokio v1.17.0 ()
│ │ └── tokio-util v0.6.9
│ │ └── tokio v1.17.0 ()
│ ├── tokio v1.17.0 ()
│ ├── tokio-util v0.6.9 ()
├── tokio v1.17.0 ()
├── tokio-executor-trait v2.1.0
│ └── tokio v1.17.0 ()
├── tokio-reactor-trait v1.1.0
│ ├── tokio v1.17.0 ()
│ └── tokio-stream v0.1.8
│ └── tokio v1.17.0 ()
└── tokio-retry v0.3.0
└── tokio v1.17.0 ()
Platform
The output of
uname -a
(UNIX), or version and 32 or 64-bit (Windows)Linux localhost 5.18.14-arch1-1 #1 SMP PREEMPT_DYNAMIC Sat, 23 Jul 2022 11:46:17 +0000 x86_64 GNU/Linux
Description
I'm fairly new to rust, so I might not do something correctly, but here is what I observe:
I use tokio to communicate with multiple cameras over TCP sockets. XML commands can be sent to and XML messages can be received from the cameras. The delimiter that marks the end of a message is the NULL byte
b'\0'
. I useread_until
to read a single message from the socket. It works 99% of the time, but from time to time I get 2 messages in the buffer with 2 NULL bytes (one being at the end correctly). So it seems like sometimesread_until
can "miss" the delimiter.I tried this code:
The relevant code part looks like this:
I expected to see this happen:
I would expect that we never enter into the 'Temp error checking' code part, since we have only one NULL byte at the end of
stream.read_buffer: Vec<u8>
Instead, this happened:
Sometimes we got in there (error checking part) and if I check the content of
BAD_XML.xml
I indeed see 2 messages and 2 NULL bytes at the end of those. I also log the return value of theread_until
call and thestream.read_buffer
which gives this:I know that
len
can be smaller than thestream.read_buffer.len()
if cancellation happen, I just thought it be worth mentioning that the first NULL bytes is at position 251157 which is a different value.Additional information
tokio::select!
branch.cargo build --release --target=x86_64-unknown-linux-musl
and is run on a server as a systemd service. The server platform is:Linux ... 4.15.0-188-generic #199-Ubuntu SMP Wed Jun 15 20:42:56 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
.The text was updated successfully, but these errors were encountered: