@@ -10,6 +10,7 @@ use std::fs::File;
10
10
use std:: os:: unix:: io:: { AsRawFd , FromRawFd , IntoRawFd } ;
11
11
use std:: os:: unix:: net:: UnixStream ;
12
12
use std:: ptr;
13
+ use std:: time:: Duration ;
13
14
14
15
use serde:: { Deserialize , Serialize } ;
15
16
use userfaultfd:: { Error , Event , Uffd } ;
@@ -52,38 +53,41 @@ pub struct UffdHandler {
52
53
}
53
54
54
55
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
+
55
73
fn get_mappings_and_file ( stream : & UnixStream ) -> ( String , File ) {
56
74
// Sometimes, reading from the stream succeeds but we don't receive any
57
75
// UFFD descriptor. We don't really have a good understanding why this is
58
76
// happening, but let's try to be a bit more robust and retry a few times
59
77
// before we declare defeat.
60
78
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) ;
67
82
}
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..." ) ;
84
85
}
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 ) ) ;
87
91
}
88
92
89
93
panic ! ( "Could not get UFFD and mappings after 5 retries" ) ;
0 commit comments