|
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 exclusivley owned file descriptor is one that no |
| 247 | +//! other code is allowed to close, but the owner is allowed to close it any time. A type that owns |
| 248 | +//! its file descriptor should close it in its `drop` function. Types like [`File`] generally own |
| 249 | +//! their file descriptor. Similarly, file descriptors can be *borrowed*. This indicates that the |
| 250 | +//! file descriptor will not be closed for the lifetime of the borrow, but it does *not* imply any |
| 251 | +//! right to close this file descriptor, since it will likely be owned by someone else. |
| 252 | +//! |
| 253 | +//! The platform-specific parts of the Rust standard library expose types that reflect these |
| 254 | +//! concepts, see [`os::unix`] and [`os::windows`]. |
| 255 | +//! |
| 256 | +//! To uphold I/O safety, it is crucial that no code closes file descriptors it does not own. In |
| 257 | +//! other words, a safe function that takes a regular integer, treats it as a file descriptor, and |
| 258 | +//! closes it, is *unsound*. |
| 259 | +//! |
| 260 | +//! Note that this does not talk about performing other operations on the file descriptor, such as |
| 261 | +//! reading or writing. For example, on Unix, the [`OwnedFd`] and [`BorrowedFd`] types from the |
| 262 | +//! standard library do *not* exclude that there is other code that reads or writes the same |
| 263 | +//! underlying object, and indeed there exist safe functions like `BorrowedFd::try_clone_to_owned` |
| 264 | +//! that can be used to read or write an object even after the end of the borrow. However, user code |
| 265 | +//! might want to rely on keeping the object behind a file descriptor completely private and |
| 266 | +//! protected against reads or writes from other parts of the program. Whether that is sound is |
| 267 | +//! [currently unclear](https://github.com/rust-lang/rust/issues/114167). Certainly, `OwnedFd` as a |
| 268 | +//! type does not provide any promise that the underlying file descriptor has not been cloned. |
| 269 | +//! |
241 | 270 | //! [`File`]: crate::fs::File
|
242 | 271 | //! [`TcpStream`]: crate::net::TcpStream
|
243 | 272 | //! [`io::stdout`]: stdout
|
244 | 273 | //! [`io::Result`]: self::Result
|
245 | 274 | //! [`?` operator]: ../../book/appendix-02-operators.html
|
246 | 275 | //! [`Result`]: crate::result::Result
|
247 | 276 | //! [`.unwrap()`]: crate::result::Result::unwrap
|
| 277 | +//! [I/O safety]: https://rust-lang.github.io/rfcs/3128-io-safety.html |
| 278 | +//! [`os::unix`]: ../os/unix/io/index.html |
| 279 | +//! [`os::windows`]: ../os/windows/io/index.html |
| 280 | +//! [`OwnedFd`]: ../os/fd/struct.OwnedFd.html |
| 281 | +//! [`BorrowedFd`]: ../os/fd/struct.BorrowedFd.html |
248 | 282 |
|
249 | 283 | #![stable(feature = "rust1", since = "1.0.0")]
|
250 | 284 |
|
|
0 commit comments