File tree 2 files changed +35
-1
lines changed
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 {
176
176
// something like EINTR), we might close another valid file descriptor
177
177
// opened after we closed ours.
178
178
#[ 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
+ }
180
193
#[ cfg( target_os = "hermit" ) ]
181
194
let _ = hermit_abi:: close ( self . fd ) ;
182
195
}
Original file line number Diff line number Diff line change @@ -870,6 +870,27 @@ impl Iterator for ReadDir {
870
870
871
871
impl Drop for Dir {
872
872
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
+ }
873
894
let r = unsafe { libc:: closedir ( self . 0 ) } ;
874
895
assert ! (
875
896
r == 0 || crate :: io:: Error :: last_os_error( ) . is_interrupted( ) ,
You can’t perform that action at this time.
0 commit comments