|
12 | 12 | //! | Type | Analogous to |
|
13 | 13 | //! | ------------------ | ------------ |
|
14 | 14 | //! | [`RawFd`] | `*const _` |
|
15 |
| -//! | [`BorrowedFd<'a>`] | `&'a _` | |
16 |
| -//! | [`OwnedFd`] | `Box<_>` | |
| 15 | +//! | [`BorrowedFd<'a>`] | `&'a Arc<_>` | |
| 16 | +//! | [`OwnedFd`] | `Arc<_>` | |
17 | 17 | //!
|
18 | 18 | //! Like raw pointers, `RawFd` values are primitive values. And in new code,
|
19 | 19 | //! they should be considered unsafe to do I/O on (analogous to dereferencing
|
|
23 | 23 | //! either by adding `unsafe` to APIs that dereference `RawFd` values, or by
|
24 | 24 | //! using to `BorrowedFd` or `OwnedFd` instead.
|
25 | 25 | //!
|
| 26 | +//! The use of `Arc` for borrowed/owned file descriptors may be surprising. Unix file descriptors |
| 27 | +//! are mere references to internal kernel objects called "open file descriptions", and the same |
| 28 | +//! open file description can be referenced by multiple file descriptors (e.g. if `dup` is used). |
| 29 | +//! State such as the offset within the file is shared among all file descriptors that refer to the |
| 30 | +//! same open file description, and the kernel internally does reference-counting to only close the |
| 31 | +//! underlying resource once all file descriptors referencing it are closed. That's why `Arc` (and |
| 32 | +//! not `Box`) is the closest Rust analogy to an "owned" file descriptor. |
| 33 | +//! |
26 | 34 | //! Like references, `BorrowedFd` values are tied to a lifetime, to ensure
|
27 | 35 | //! that they don't outlive the resource they point to. These are safe to
|
28 | 36 | //! use. `BorrowedFd` values may be used in APIs which provide safe access to
|
29 | 37 | //! any system call except for:
|
30 | 38 | //!
|
31 | 39 | //! - `close`, because that would end the dynamic lifetime of the resource
|
32 |
| -//! without ending the lifetime of the file descriptor. |
| 40 | +//! without ending the lifetime of the file descriptor. (Equivalently: |
| 41 | +//! an `&Arc<_>` cannot be `drop`ed.) |
33 | 42 | //!
|
34 | 43 | //! - `dup2`/`dup3`, in the second argument, because this argument is
|
35 |
| -//! closed and assigned a new resource, which may break the assumptions |
| 44 | +//! closed and assigned a new resource, which may break the assumptions of |
36 | 45 | //! other code using that file descriptor.
|
37 | 46 | //!
|
38 |
| -//! `BorrowedFd` values may be used in APIs which provide safe access to `dup` |
39 |
| -//! system calls, so types implementing `AsFd` or `From<OwnedFd>` should not |
40 |
| -//! assume they always have exclusive access to the underlying file |
41 |
| -//! description. |
| 47 | +//! `BorrowedFd` values may be used in APIs which provide safe access to `dup` system calls, so code |
| 48 | +//! working with `OwnedFd` cannot assume to have exclusive access to the underlying open file |
| 49 | +//! description. (Equivalently: `&Arc` may be used in APIs that provide safe access to `clone`, so |
| 50 | +//! code working with an `Arc` cannot assume that the reference count is 1.) |
42 | 51 | //!
|
43 | 52 | //! `BorrowedFd` values may also be used with `mmap`, since `mmap` uses the
|
44 | 53 | //! provided file descriptor in a manner similar to `dup` and does not require
|
|
52 | 61 | //! take full responsibility for ensuring that safe Rust code cannot evoke
|
53 | 62 | //! undefined behavior through it.
|
54 | 63 | //!
|
55 |
| -//! Like boxes, `OwnedFd` values conceptually own the resource they point to, |
56 |
| -//! and free (close) it when they are dropped. |
| 64 | +//! Like `Arc`, `OwnedFd` values conceptually own one reference to the resource they point to, |
| 65 | +//! and decrement the reference count when they are dropped (by calling `close`). |
| 66 | +//! When the reference count reaches 0, the underlying open file description will be freed |
| 67 | +//! by the kernel. |
57 | 68 | //!
|
58 | 69 | //! See the [`io` module docs][io-safety] for a general explanation of I/O safety.
|
59 | 70 | //!
|
|
0 commit comments