about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-08-27 18:59:27 +0200
committerGitHub <noreply@github.com>2024-08-27 18:59:27 +0200
commit6ab180577f5eea2c31e17d45111ee6a5993e59b5 (patch)
treeade0061912d400def36c76f2f59625fbd048b5b2
parent849c240c1e93337800c2447947cda7fc1e8f0ca1 (diff)
parent21dd88f963f8047fa6a3d0492fc7dcf86f5e5f4d (diff)
downloadrust-6ab180577f5eea2c31e17d45111ee6a5993e59b5.tar.gz
rust-6ab180577f5eea2c31e17d45111ee6a5993e59b5.zip
Rollup merge of #129581 - RalfJung:exit, r=joshtriplett
exit: explain our expectations for the exit handlers registered in a Rust program

This documents the position of ``@Amanieu`` and others in https://github.com/rust-lang/rust/issues/126600: a library with an atexit handler that destroys state that other threads could still be working on is buggy. We do not consider it acceptable for a library to say "you must call the following cleanup function before exiting from `main` or calling `exit`". I don't know if this is established ``@rust-lang/libs-api``  consensus so I presume this will have to go through FCP.

Given that Rust supports concurrency, I don't think there is any way to write a sound Rust wrapper around a library that has such a required cleanup function: even if we made `exit` unsafe, and the Rust wrapper used the scope-with-callback approach to ensure it can run cleanup code before returning from the wrapper (like `thread::scope`), one could still call this wrapper in a second thread and then return from `main` while the wrapper runs. Making this sound would require `std` to provide a way to "block" returning from `main`, so that while the wrapper runs returning from `main` waits until the wrapper is done... that just doesn't seem feasible.

The `exit` docs do not seem like the best place to document this, but I also couldn't think of a better one.
-rw-r--r--library/std/src/process.rs9
1 files changed, 9 insertions, 0 deletions
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 9ffdebe1b6f..bbea27ebc10 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -2296,6 +2296,15 @@ impl Child {
 /// }
 /// ```
 ///
+/// In its current implementation, this function will execute exit handlers registered with `atexit`
+/// as well as other platform-specific exit handlers (e.g. `fini` sections of ELF shared objects).
+/// This means that Rust requires that all exit handlers are safe to execute at any time. In
+/// particular, if an exit handler cleans up some state that might be concurrently accessed by other
+/// threads, it is required that the exit handler performs suitable synchronization with those
+/// threads. (The alternative to this requirement would be to not run exit handlers at all, which is
+/// considered undesirable. Note that returning from `main` also calls `exit`, so making `exit` an
+/// unsafe operation is not an option.)
+///
 /// ## Platform-specific behavior
 ///
 /// **Unix**: On Unix-like platforms, it is unlikely that all 32 bits of `exit`