Skip to content

Commit 099ff28

Browse files
committed
Document the double-close risk with unistd::close
1 parent a91348b commit 099ff28

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

src/unistd.rs

+34
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,40 @@ pub fn gethostname<'a>(buffer: &'a mut [u8]) -> Result<&'a CStr> {
668668
})
669669
}
670670

671+
/// Close a raw file descriptor
672+
///
673+
/// Be aware that many Rust types implicitly close-on-drop, including
674+
/// `std::fs::File`. Explicitly closing them with this method too can result in
675+
/// a double-close condition, which can cause confusing `EBADF` errors in
676+
/// seemingly unrelated code. Caveat programmer.
677+
///
678+
/// # Examples
679+
///
680+
/// ```no_run
681+
/// extern crate tempfile;
682+
/// extern crate nix;
683+
///
684+
/// use std::os::unix::io::AsRawFd;
685+
/// use nix::unistd::close;
686+
///
687+
/// fn main() {
688+
/// let mut f = tempfile::tempfile().unwrap();
689+
/// close(f.as_raw_fd()).unwrap(); // Bad! f will also close on drop!
690+
/// }
691+
/// ```
692+
///
693+
/// ```rust
694+
/// extern crate tempfile;
695+
/// extern crate nix;
696+
///
697+
/// use std::os::unix::io::IntoRawFd;
698+
/// use nix::unistd::close;
699+
///
700+
/// fn main() {
701+
/// let mut f = tempfile::tempfile().unwrap();
702+
/// close(f.into_raw_fd()).unwrap(); // Good. into_raw_fd consumes f
703+
/// }
704+
/// ```
671705
pub fn close(fd: RawFd) -> Result<()> {
672706
let res = unsafe { libc::close(fd) };
673707
Errno::result(res).map(drop)

0 commit comments

Comments
 (0)