File tree Expand file tree Collapse file tree 2 files changed +35
-1
lines changed Expand file tree Collapse file tree 2 files changed +35
-1
lines changed Original file line number Diff line number Diff line change @@ -176,7 +176,20 @@ impl Drop for OwnedFd {
176176 // something like EINTR), we might close another valid file descriptor
177177 // opened after we closed ours.
178178 #[ cfg( not( target_os = "hermit" ) ) ]
179- let _ = libc:: close ( self . fd ) ;
179+ {
180+ use crate :: sys:: os:: errno;
181+ // ideally this would use assert_unsafe_precondition!, but that's only in core
182+ if cfg ! ( debug_assertions) {
183+ // close() can bubble up error codes from FUSE which can send semantically
184+ // inappropriate error codes including EBADF.
185+ // So we check file flags instead which live on the file descriptor and not the underlying file.
186+ // The downside is that it costs an extra syscall, so we only do it for debug.
187+ if libc:: fcntl ( self . fd , libc:: F_GETFD ) == -1 && errno ( ) == libc:: EBADF {
188+ rtabort ! ( "IO Safety violation: owned file descriptor already closed" ) ;
189+ }
190+ }
191+ let _ = libc:: close ( self . fd ) ;
192+ }
180193 #[ cfg( target_os = "hermit" ) ]
181194 let _ = hermit_abi:: close ( self . fd ) ;
182195 }
Original file line number Diff line number Diff line change @@ -870,6 +870,27 @@ impl Iterator for ReadDir {
870870
871871impl Drop for Dir {
872872 fn drop ( & mut self ) {
873+ // ideally this would use assert_unsafe_precondition!, but that's only in core
874+ #[ cfg( all(
875+ debug_assertions,
876+ not( any(
877+ target_os = "redox" ,
878+ target_os = "nto" ,
879+ target_os = "vita" ,
880+ target_os = "hurd" ,
881+ ) )
882+ ) ) ]
883+ {
884+ use crate :: sys:: os:: errno;
885+ // close() can bubble up error codes from FUSE which can send semantically
886+ // inappropriate error codes including EBADF.
887+ // So we check file flags instead which live on the file descriptor and not the underlying file.
888+ // The downside is that it costs an extra syscall, so we only do it for debug.
889+ let fd = unsafe { libc:: dirfd ( self . 0 ) } ;
890+ if unsafe { libc:: fcntl ( fd, libc:: F_GETFD ) } == -1 && errno ( ) == libc:: EBADF {
891+ rtabort ! ( "IO Safety violation: DIR*'s owned file descriptor already closed" ) ;
892+ }
893+ }
873894 let r = unsafe { libc:: closedir ( self . 0 ) } ;
874895 assert ! (
875896 r == 0 || crate :: io:: Error :: last_os_error( ) . is_interrupted( ) ,
You can’t perform that action at this time.
0 commit comments