|
5 | 5 | //! the [`Read`] and [`Write`] traits, which provide the
|
6 | 6 | //! most general interface for reading and writing input and output.
|
7 | 7 | //!
|
8 |
| -//! # Read and Write |
| 8 | +//! ## Read and Write |
9 | 9 | //!
|
10 | 10 | //! Because they are traits, [`Read`] and [`Write`] are implemented by a number
|
11 | 11 | //! of other types, and you can implement them for your types too. As such,
|
|
238 | 238 | //! contract. The implementation of many of these functions are subject to change over
|
239 | 239 | //! time and may call fewer or more syscalls/library functions.
|
240 | 240 | //!
|
| 241 | +//! ## I/O Safety |
| 242 | +//! |
| 243 | +//! Rust follows an I/O safety discipline that is comparable to its memory safety discipline. This |
| 244 | +//! means that file descriptors can be *exclusively owned*. (Here, "file descriptor" is meant to |
| 245 | +//! subsume similar concepts that exist across a wide range of operating systems even if they might |
| 246 | +//! use a different name, such as "handle".) An exclusively owned file descriptor is one that no |
| 247 | +//! other code is allowed to access in any way, but the owner is allowed to access and even close |
| 248 | +//! it any time. A type that owns its file descriptor should usually close it in its `drop` |
| 249 | +//! function. Types like [`File`] own their file descriptor. Similarly, file descriptors |
| 250 | +//! can be *borrowed*, granting the temporary right to perform operations on this file descriptor. |
| 251 | +//! This indicates that the file descriptor will not be closed for the lifetime of the borrow, but |
| 252 | +//! it does *not* imply any right to close this file descriptor, since it will likely be owned by |
| 253 | +//! someone else. |
| 254 | +//! |
| 255 | +//! The platform-specific parts of the Rust standard library expose types that reflect these |
| 256 | +//! concepts, see [`os::unix`] and [`os::windows`]. |
| 257 | +//! |
| 258 | +//! To uphold I/O safety, it is crucial that no code acts on file descriptors it does not own or |
| 259 | +//! borrow, and no code closes file descriptors it does not own. In other words, a safe function |
| 260 | +//! that takes a regular integer, treats it as a file descriptor, and acts on it, is *unsound*. |
| 261 | +//! |
| 262 | +//! Not upholding I/O safety and acting on a file descriptor without proof of ownership can lead to |
| 263 | +//! misbehavior and even Undefined Behavior in code that relies on ownership of its file |
| 264 | +//! descriptors: a closed file descriptor could be re-allocated, so the original owner of that file |
| 265 | +//! descriptor is now working on the wrong file. Some code might even rely on fully encapsulating |
| 266 | +//! its file descriptors with no operations being performed by any other part of the program. |
| 267 | +//! |
| 268 | +//! Note that exclusive ownership of a file descriptor does *not* imply exclusive ownership of the |
| 269 | +//! underlying kernel object that the file descriptor references (also called "file description" on |
| 270 | +//! some operating systems). File descriptors basically work like [`Arc`]: when you receive an owned |
| 271 | +//! file descriptor, you cannot know whether there are any other file descriptors that reference the |
| 272 | +//! same kernel object. However, when you create a new kernel object, you know that you are holding |
| 273 | +//! the only reference to it. Just be careful not to lend it to anyone, since they can obtain a |
| 274 | +//! clone and then you can no longer know what the reference count is! In that sense, [`OwnedFd`] is |
| 275 | +//! like `Arc` and [`BorrowedFd<'a>`] is like `&'a Arc` (and similar for the Windows types). In |
| 276 | +//! particular, given a `BorrowedFd<'a>`, you are not allowed to close the file descriptor -- just |
| 277 | +//! like how, given a `&'a Arc`, you are not allowed to decrement the reference count and |
| 278 | +//! potentially free the underlying object. There is no equivalent to `Box` for file descriptors in |
| 279 | +//! the standard library (that would be a type that guarantees that the reference count is `1`), |
| 280 | +//! however, it would be possible for a crate to define a type with those semantics. |
| 281 | +//! |
241 | 282 | //! [`File`]: crate::fs::File
|
242 | 283 | //! [`TcpStream`]: crate::net::TcpStream
|
243 | 284 | //! [`io::stdout`]: stdout
|
244 | 285 | //! [`io::Result`]: self::Result
|
245 | 286 | //! [`?` operator]: ../../book/appendix-02-operators.html
|
246 | 287 | //! [`Result`]: crate::result::Result
|
247 | 288 | //! [`.unwrap()`]: crate::result::Result::unwrap
|
| 289 | +//! [`os::unix`]: ../os/unix/io/index.html |
| 290 | +//! [`os::windows`]: ../os/windows/io/index.html |
| 291 | +//! [`OwnedFd`]: ../os/fd/struct.OwnedFd.html |
| 292 | +//! [`BorrowedFd<'a>`]: ../os/fd/struct.BorrowedFd.html |
| 293 | +//! [`Arc`]: crate::sync::Arc |
248 | 294 |
|
249 | 295 | #![stable(feature = "rust1", since = "1.0.0")]
|
250 | 296 |
|
|
0 commit comments