File tree 2 files changed +34
-1
lines changed
2 files changed +34
-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,26 @@ 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
+ // close() can bubble up error codes from FUSE which can send semantically
885
+ // inappropriate error codes including EBADF.
886
+ // So we check file flags instead which live on the file descriptor and not the underlying file.
887
+ // The downside is that it costs an extra syscall, so we only do it for debug.
888
+ let fd = libc:: dirfd ( self . 0 ) ;
889
+ if libc:: fcntl ( fd, libc:: F_GETFD ) == -1 && errno ( ) == libc:: EBADF {
890
+ rtabort ! ( "IO Safety violation: DIR*'s owned file descriptor already closed" ) ;
891
+ }
892
+ }
873
893
let r = unsafe { libc:: closedir ( self . 0 ) } ;
874
894
assert ! (
875
895
r == 0 || crate :: io:: Error :: last_os_error( ) . is_interrupted( ) ,
You can’t perform that action at this time.
0 commit comments