about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-04-26 19:04:23 +0200
committerRalf Jung <post@ralfj.de>2024-04-27 09:40:55 +0200
commit6b6bc9805ddeebf35fec63844e6f00f06059650a (patch)
treebb700fe32aea52914fc7bf1114bd64db69676584
parent9adafa7f8d72461426def828b5a8735a97eddc3f (diff)
downloadrust-6b6bc9805ddeebf35fec63844e6f00f06059650a.tar.gz
rust-6b6bc9805ddeebf35fec63844e6f00f06059650a.zip
io safety: update Unix explanation
-rw-r--r--library/std/src/io/mod.rs2
-rw-r--r--library/std/src/os/unix/io/mod.rs31
2 files changed, 22 insertions, 11 deletions
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 98973a43e1d..a3fdcdc2d07 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -266,7 +266,7 @@
 //! its file descriptors with no operations being performed by any other part of the program.
 //!
 //! Note that exclusive ownership of a file descriptor does *not* imply exclusive ownership of the
-//! underlying kernel object that the file descriptor references (also called "file description" on
+//! underlying kernel object that the file descriptor references (also called "open file description" on
 //! some operating systems). File descriptors basically work like [`Arc`]: when you receive an owned
 //! file descriptor, you cannot know whether there are any other file descriptors that reference the
 //! same kernel object. However, when you create a new kernel object, you know that you are holding
diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs
index 827278f8b26..6d4090ee31c 100644
--- a/library/std/src/os/unix/io/mod.rs
+++ b/library/std/src/os/unix/io/mod.rs
@@ -12,8 +12,8 @@
 //! | Type               | Analogous to |
 //! | ------------------ | ------------ |
 //! | [`RawFd`]          | `*const _`   |
-//! | [`BorrowedFd<'a>`] | `&'a _`      |
-//! | [`OwnedFd`]        | `Box<_>`     |
+//! | [`BorrowedFd<'a>`] | `&'a Arc<_>` |
+//! | [`OwnedFd`]        | `Arc<_>`     |
 //!
 //! Like raw pointers, `RawFd` values are primitive values. And in new code,
 //! they should be considered unsafe to do I/O on (analogous to dereferencing
@@ -23,22 +23,31 @@
 //! either by adding `unsafe` to APIs that dereference `RawFd` values, or by
 //! using to `BorrowedFd` or `OwnedFd` instead.
 //!
+//! The use of `Arc` for borrowed/owned file descriptors may be surprising. Unix file descriptors
+//! are mere references to internal kernel objects called "open file descriptions", and the same
+//! open file description can be referenced by multiple file descriptors (e.g. if `dup` is used).
+//! State such as the offset within the file is shared among all file descriptors that refer to the
+//! same open file description, and the kernel internally does reference-counting to only close the
+//! underlying resource once all file descriptors referencing it are closed. That's why `Arc` (and
+//! not `Box`) is the closest Rust analogy to an "owned" file descriptor.
+//!
 //! Like references, `BorrowedFd` values are tied to a lifetime, to ensure
 //! that they don't outlive the resource they point to. These are safe to
 //! use. `BorrowedFd` values may be used in APIs which provide safe access to
 //! any system call except for:
 //!
 //!  - `close`, because that would end the dynamic lifetime of the resource
-//!    without ending the lifetime of the file descriptor.
+//!    without ending the lifetime of the file descriptor. (Equivalently:
+//!    an `&Arc<_>` cannot be `drop`ed.)
 //!
 //!  - `dup2`/`dup3`, in the second argument, because this argument is
-//!    closed and assigned a new resource, which may break the assumptions
+//!    closed and assigned a new resource, which may break the assumptions of
 //!    other code using that file descriptor.
 //!
-//! `BorrowedFd` values may be used in APIs which provide safe access to `dup`
-//! system calls, so types implementing `AsFd` or `From<OwnedFd>` should not
-//! assume they always have exclusive access to the underlying file
-//! description.
+//! `BorrowedFd` values may be used in APIs which provide safe access to `dup` system calls, so code
+//! working with `OwnedFd` cannot assume to have exclusive access to the underlying open file
+//! description. (Equivalently: `&Arc` may be used in APIs that provide safe access to `clone`, so
+//! code working with an `Arc` cannot assume that the reference count is 1.)
 //!
 //! `BorrowedFd` values may also be used with `mmap`, since `mmap` uses the
 //! provided file descriptor in a manner similar to `dup` and does not require
@@ -52,8 +61,10 @@
 //! take full responsibility for ensuring that safe Rust code cannot evoke
 //! undefined behavior through it.
 //!
-//! Like boxes, `OwnedFd` values conceptually own the resource they point to,
-//! and free (close) it when they are dropped.
+//! Like `Arc`, `OwnedFd` values conceptually own one reference to the resource they point to,
+//! and decrement the reference count when they are dropped (by calling `close`).
+//! When the reference count reaches 0, the underlying open file description will be freed
+//! by the kernel.
 //!
 //! See the [`io` module docs][io-safety] for a general explanation of I/O safety.
 //!