Skip to content

Commit 69522c8

Browse files
committed
fix: sleep between retries during UFFD handler negotiation
During fc85170, we changed the UFFD handler logic to retry the negotiation with Firecracker up to 5 times in case of failures. Retries happen immediately. Add a small timeout between retries to make this even more robust. Signed-off-by: Babis Chalios <[email protected]>
1 parent aa73f45 commit 69522c8

File tree

1 file changed

+28
-24
lines changed

1 file changed

+28
-24
lines changed

src/firecracker/examples/uffd/uffd_utils.rs

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::fs::File;
1010
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
1111
use std::os::unix::net::UnixStream;
1212
use std::ptr;
13+
use std::time::Duration;
1314

1415
use serde::{Deserialize, Serialize};
1516
use userfaultfd::{Error, Event, Uffd};
@@ -52,38 +53,41 @@ pub struct UffdHandler {
5253
}
5354

5455
impl UffdHandler {
56+
fn try_get_mappings_and_file(
57+
stream: &UnixStream,
58+
) -> Result<(String, Option<File>), std::io::Error> {
59+
let mut message_buf = vec![0u8; 1024];
60+
let (bytes_read, file) = stream.recv_with_fd(&mut message_buf[..])?;
61+
message_buf.resize(bytes_read, 0);
62+
63+
// We do not expect to receive non-UTF-8 data from Firecracker, so this is probably
64+
// an error we can't recover from. Just immediately abort
65+
let body = String::from_utf8(message_buf.clone()).unwrap_or_else(|_| {
66+
panic!(
67+
"Received body is not a utf-8 valid string. Raw bytes received: {message_buf:#?}"
68+
)
69+
});
70+
Ok((body, file))
71+
}
72+
5573
fn get_mappings_and_file(stream: &UnixStream) -> (String, File) {
5674
// Sometimes, reading from the stream succeeds but we don't receive any
5775
// UFFD descriptor. We don't really have a good understanding why this is
5876
// happening, but let's try to be a bit more robust and retry a few times
5977
// before we declare defeat.
6078
for _ in 1..=5 {
61-
let mut message_buf = vec![0u8; 1024];
62-
let (bytes_read, file) = match stream.recv_with_fd(&mut message_buf[..]) {
63-
Ok(res) => res,
64-
Err(err) => {
65-
println!("Could not receive message from stream: {err}");
66-
continue;
79+
match Self::try_get_mappings_and_file(stream) {
80+
Ok((body, Some(file))) => {
81+
return (body, file);
6782
}
68-
};
69-
message_buf.resize(bytes_read, 0);
70-
71-
// We do not expect to receive non-UTF-8 data from Firecracker, so this is probably
72-
// an error we can't recover from. Just immediately abort
73-
let body = String::from_utf8(message_buf.clone()).unwrap_or_else(|_| {
74-
panic!(
75-
"Received body is not a utf-8 valid string. Raw bytes received: \
76-
{message_buf:#?}"
77-
)
78-
});
79-
let file = match file {
80-
Some(file) => file,
81-
None => {
82-
println!("Did not receive Uffd from UDS. Received body: {body}");
83-
continue;
83+
Ok((body, None)) => {
84+
println!("Didn't receive UFFD over socket. We received: '{body}'. Retrying...");
8485
}
85-
};
86-
return (body, file);
86+
Err(err) => {
87+
println!("Could not get UFFD and mapping from Firecracker: {err}. Retrying...");
88+
}
89+
}
90+
std::thread::sleep(Duration::from_millis(100));
8791
}
8892

8993
panic!("Could not get UFFD and mappings after 5 retries");

0 commit comments

Comments
 (0)