@@ -15,6 +15,7 @@ use shims::time::system_time_to_duration;
1515#[ derive( Debug ) ]
1616pub struct FileHandle {
1717 file : File ,
18+ writable : bool ,
1819}
1920
2021pub struct FileHandler {
@@ -56,10 +57,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
5657 if ( o_rdonly | o_wronly | o_rdwr) & !0b11 != 0 {
5758 throw_unsup_format ! ( "Access mode flags on this platform are unsupported" ) ;
5859 }
60+ let mut writable = true ;
61+
5962 // Now we check the access mode
6063 let access_mode = flag & 0b11 ;
6164
6265 if access_mode == o_rdonly {
66+ writable = false ;
6367 options. read ( true ) ;
6468 } else if access_mode == o_wronly {
6569 options. write ( true ) ;
@@ -105,7 +109,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
105109 let fd = options. open ( & path) . map ( |file| {
106110 let mut fh = & mut this. machine . file_handler ;
107111 fh. low += 1 ;
108- fh. handles . insert ( fh. low , FileHandle { file } ) . unwrap_none ( ) ;
112+ fh. handles . insert ( fh. low , FileHandle { file, writable } ) . unwrap_none ( ) ;
109113 fh. low
110114 } ) ;
111115
@@ -148,13 +152,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
148152 let fd = this. read_scalar ( fd_op) ?. to_i32 ( ) ?;
149153
150154 if let Some ( handle) = this. machine . file_handler . handles . remove ( & fd) {
151- // `File::sync_all` does the checks that are done when closing a file. We do this to
152- // to handle possible errors correctly.
153- let result = this. try_unwrap_io_result ( handle. file . sync_all ( ) . map ( |_| 0i32 ) ) ;
154- // Now we actually close the file.
155- drop ( handle) ;
156- // And return the result.
157- result
155+ // We sync the file if it was opened in a mode different than read-only.
156+ if handle. writable {
157+ // `File::sync_all` does the checks that are done when closing a file. We do this to
158+ // to handle possible errors correctly.
159+ let result = this. try_unwrap_io_result ( handle. file . sync_all ( ) . map ( |_| 0i32 ) ) ;
160+ // Now we actually close the file.
161+ drop ( handle) ;
162+ // And return the result.
163+ result
164+ } else {
165+ // We drop the file, this closes it but ignores any errors produced when closing
166+ // it. This is done because `File::sync_call` cannot be done over files like
167+ // `/dev/urandom` which are read-only. Check
168+ // https://github.com/rust-lang/miri/issues/999#issuecomment-568920439 for a deeper
169+ // discussion.
170+ drop ( handle) ;
171+ Ok ( 0 )
172+ }
158173 } else {
159174 this. handle_not_found ( )
160175 }
0 commit comments