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