@@ -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,42 @@ 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: \
68+ {message_buf:#?}"
69+ )
70+ } ) ;
71+ Ok ( ( body, file) )
72+ }
73+
5574 fn get_mappings_and_file ( stream : & UnixStream ) -> ( String , File ) {
5675 // Sometimes, reading from the stream succeeds but we don't receive any
5776 // UFFD descriptor. We don't really have a good understanding why this is
5877 // happening, but let's try to be a bit more robust and retry a few times
5978 // before we declare defeat.
6079 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 ;
80+ match Self :: try_get_mappings_and_file ( stream) {
81+ Ok ( ( body, Some ( file) ) ) => {
82+ return ( body, file) ;
6783 }
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 ;
84+ Ok ( ( body, None ) ) => {
85+ println ! ( "Didn't receive UFFD over socket. We received: '{body}'. Retrying..." ) ;
8486 }
85- } ;
86- return ( body, file) ;
87+ Err ( err) => {
88+ println ! ( "Could not get UFFD and mapping from Firecracker: {err}. Retrying..." ) ;
89+ }
90+ }
91+ std:: thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
8792 }
8893
8994 panic ! ( "Could not get UFFD and mappings after 5 retries" ) ;
0 commit comments