1
Fork 0

Rollup merge of #124412 - RalfJung:io-safety, r=Amanieu

io safety: update Unix explanation to use `Arc`

Fixes https://github.com/rust-lang/rust/issues/124384

Cc ```@jsgf```
This commit is contained in:
Matthias Krüger 2024-05-03 06:04:19 +02:00 committed by GitHub
commit 9ab5cfd91e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 22 additions and 11 deletions

View file

@ -266,7 +266,7 @@
//! its file descriptors with no operations being performed by any other part of the program. //! 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 //! 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 //! 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 //! 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 //! same kernel object. However, when you create a new kernel object, you know that you are holding

View file

@ -12,8 +12,8 @@
//! | Type | Analogous to | //! | Type | Analogous to |
//! | ------------------ | ------------ | //! | ------------------ | ------------ |
//! | [`RawFd`] | `*const _` | //! | [`RawFd`] | `*const _` |
//! | [`BorrowedFd<'a>`] | `&'a _` | //! | [`BorrowedFd<'a>`] | `&'a Arc<_>` |
//! | [`OwnedFd`] | `Box<_>` | //! | [`OwnedFd`] | `Arc<_>` |
//! //!
//! Like raw pointers, `RawFd` values are primitive values. And in new code, //! 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 //! 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 //! either by adding `unsafe` to APIs that dereference `RawFd` values, or by
//! using to `BorrowedFd` or `OwnedFd` instead. //! 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 //! 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 //! 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 //! use. `BorrowedFd` values may be used in APIs which provide safe access to
//! any system call except for: //! any system call except for:
//! //!
//! - `close`, because that would end the dynamic lifetime of the resource //! - `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 //! - `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. //! other code using that file descriptor.
//! //!
//! `BorrowedFd` values may be used in APIs which provide safe access to `dup` //! `BorrowedFd` values may be used in APIs which provide safe access to `dup` system calls, so code
//! system calls, so types implementing `AsFd` or `From<OwnedFd>` should not //! working with `OwnedFd` cannot assume to have exclusive access to the underlying open file
//! assume they always have exclusive access to the underlying file //! description. (Equivalently: `&Arc` may be used in APIs that provide safe access to `clone`, so
//! description. //! 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 //! `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 //! 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 //! take full responsibility for ensuring that safe Rust code cannot evoke
//! undefined behavior through it. //! undefined behavior through it.
//! //!
//! Like boxes, `OwnedFd` values conceptually own the resource they point to, //! Like `Arc`, `OwnedFd` values conceptually own one reference to the resource they point to,
//! and free (close) it when they are dropped. //! 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. //! See the [`io` module docs][io-safety] for a general explanation of I/O safety.
//! //!