@@ -10,6 +10,7 @@ use std::fs::File;
1010use std:: os:: unix:: io:: { AsRawFd , FromRawFd , IntoRawFd } ;
1111use std:: os:: unix:: net:: UnixStream ;
1212use std:: ptr;
13+ use std:: time:: Duration ;
1314
1415use serde:: { Deserialize , Serialize } ;
1516use userfaultfd:: { Error , Event , Uffd } ;
@@ -52,38 +53,41 @@ pub struct UffdHandler {
5253}
5354
5455impl 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