Skip to content

Commit 098db78

Browse files
authored
Rollup merge of rust-lang#136320 - RalfJung:exit, r=the8472
exit: document interaction with C Cc rust-lang#126600
2 parents 259fdb5 + c133e22 commit 098db78

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

library/std/src/env.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ impl Error for VarError {
333333
///
334334
/// Discussion of this unsafety on Unix may be found in:
335335
///
336-
/// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188)
336+
/// - [Austin Group Bugzilla (for POSIX)](https://austingroupbugs.net/view.php?id=188)
337337
/// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
338338
///
339339
/// To pass an environment variable to a child process, you can instead use [`Command::env`].

library/std/src/process.rs

+30-3
Original file line numberDiff line numberDiff line change
@@ -2018,9 +2018,9 @@ impl ExitCode {
20182018
///
20192019
/// Note that this has the same caveats as [`process::exit()`][exit], namely that this function
20202020
/// terminates the process immediately, so no destructors on the current stack or any other
2021-
/// thread's stack will be run. If a clean shutdown is needed, it is recommended to simply
2022-
/// return this ExitCode from the `main` function, as demonstrated in the [type
2023-
/// documentation](#examples).
2021+
/// thread's stack will be run. Also see those docs for some important notes on interop with C
2022+
/// code. If a clean shutdown is needed, it is recommended to simply return this ExitCode from
2023+
/// the `main` function, as demonstrated in the [type documentation](#examples).
20242024
///
20252025
/// # Differences from `process::exit()`
20262026
///
@@ -2326,6 +2326,33 @@ impl Child {
23262326
///
23272327
/// process::exit(0x0100);
23282328
/// ```
2329+
///
2330+
/// ### Safe interop with C code
2331+
///
2332+
/// On Unix, this function is currently implemented using the `exit` C function [`exit`][C-exit]. As
2333+
/// of C23, the C standard does not permit multiple threads to call `exit` concurrently. Rust
2334+
/// mitigates this with a lock, but if C code calls `exit`, that can still cause undefined behavior.
2335+
/// Note that returning from `main` is equivalent to calling `exit`.
2336+
///
2337+
/// Therefore, it is undefined behavior to have two concurrent threads perform the following
2338+
/// without synchronization:
2339+
/// - One thread calls Rust's `exit` function or returns from Rust's `main` function
2340+
/// - Another thread calls the C function `exit` or `quick_exit`, or returns from C's `main` function
2341+
///
2342+
/// Note that if a binary contains multiple copies of the Rust runtime (e.g., when combining
2343+
/// multiple `cdylib` or `staticlib`), they each have their own separate lock, so from the
2344+
/// perspective of code running in one of the Rust runtimes, the "outside" Rust code is basically C
2345+
/// code, and concurrent `exit` again causes undefined behavior.
2346+
///
2347+
/// Individual C implementations might provide more guarantees than the standard and permit concurrent
2348+
/// calls to `exit`; consult the documentation of your C implementation for details.
2349+
///
2350+
/// For some of the on-going discussion to make `exit` thread-safe in C, see:
2351+
/// - [Rust issue #126600](https://github.com/rust-lang/rust/issues/126600)
2352+
/// - [Austin Group Bugzilla (for POSIX)](https://austingroupbugs.net/view.php?id=1845)
2353+
/// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=31997)
2354+
///
2355+
/// [C-exit]: https://en.cppreference.com/w/c/program/exit
23292356
#[stable(feature = "rust1", since = "1.0.0")]
23302357
#[cfg_attr(not(test), rustc_diagnostic_item = "process_exit")]
23312358
pub fn exit(code: i32) -> ! {

0 commit comments

Comments
 (0)