@@ -2018,9 +2018,9 @@ impl ExitCode {
2018
2018
///
2019
2019
/// Note that this has the same caveats as [`process::exit()`][exit], namely that this function
2020
2020
/// 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).
2024
2024
///
2025
2025
/// # Differences from `process::exit()`
2026
2026
///
@@ -2326,6 +2326,33 @@ impl Child {
2326
2326
///
2327
2327
/// process::exit(0x0100);
2328
2328
/// ```
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
2329
2356
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
2330
2357
#[ cfg_attr( not( test) , rustc_diagnostic_item = "process_exit" ) ]
2331
2358
pub fn exit ( code : i32 ) -> ! {
0 commit comments