@@ -868,28 +868,39 @@ impl Iterator for ReadDir {
868868 }
869869}
870870
871+ /// Aborts the process if a file desceriptor is not open, if debug asserts are enabled
872+ ///
873+ /// Many IO syscalls can't be fully trusted about EBADF error codes because those
874+ /// might get bubbled up from a remote FUSE server rather than the file descriptor
875+ /// in the current process being invalid.
876+ ///
877+ /// So we check file flags instead which live on the file descriptor and not the underlying file.
878+ /// The downside is that it costs an extra syscall, so we only do it for debug.
879+ #[ inline]
880+ pub ( crate ) fn debug_assert_fd_is_open ( fd : RawFd ) {
881+ use crate :: sys:: os:: errno;
882+
883+ // this is similar to assert_unsafe_precondition!() but it doesn't require const
884+ if core:: ub_checks:: check_library_ub ( ) {
885+ if unsafe { libc:: fcntl ( fd, libc:: F_GETFD ) } == -1 && errno ( ) == libc:: EBADF {
886+ rtabort ! ( "IO Safety violation: owned file descriptor already closed" ) ;
887+ }
888+ }
889+ }
890+
871891impl Drop for Dir {
872892 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- ) ) ]
893+ // dirfd isn't supported everywhere
894+ #[ cfg( not( any(
895+ miri,
896+ target_os = "redox" ,
897+ target_os = "nto" ,
898+ target_os = "vita" ,
899+ target_os = "hurd" ,
900+ ) ) ) ]
883901 {
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.
889902 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- }
903+ debug_assert_fd_is_open ( fd) ;
893904 }
894905 let r = unsafe { libc:: closedir ( self . 0 ) } ;
895906 assert ! (
0 commit comments