about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-08-15 00:02:24 +0200
committerGitHub <noreply@github.com>2024-08-15 00:02:24 +0200
commit0bed4d1f1c87f88dc60e8751602934ab1ca75e5e (patch)
treed8c504243720c4e18cc7bf36b8ac143cb93cb91e
parent13a52890dde8cfeb95069d77c223ac37c0cf3a46 (diff)
parent5ae03863ded632b6cedeed29cc53e9c69fe5b56b (diff)
downloadrust-0bed4d1f1c87f88dc60e8751602934ab1ca75e5e.tar.gz
rust-0bed4d1f1c87f88dc60e8751602934ab1ca75e5e.zip
Rollup merge of #125970 - RalfJung:before_exec, r=m-ou-se
CommandExt::before_exec: deprecate safety in edition 2024

Similar to `set_var`, we had to find out after 1.0 was released that `before_exec` should have been unsafe. We partially rectified this by deprecating that function a long time ago, but since https://github.com/rust-lang/rust/pull/124636 we have the ability to also deprecate the safety of the old function and make it a *hard error* to call the old function outside `unsafe` in the next edition. So just in case anyone still uses the old function, let's ensure this can't be ignored when moving code to the new edition.

Cc `@rust-lang/libs-api`

Tracking:

- https://github.com/rust-lang/rust/issues/124866
-rw-r--r--library/std/src/os/unix/process.rs14
-rw-r--r--tests/ui/rust-2024/unsafe-before_exec.e2024.stderr11
-rw-r--r--tests/ui/rust-2024/unsafe-before_exec.rs17
3 files changed, 39 insertions, 3 deletions
diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs
index c53423675bd..46202441d4e 100644
--- a/library/std/src/os/unix/process.rs
+++ b/library/std/src/os/unix/process.rs
@@ -109,13 +109,21 @@ pub trait CommandExt: Sealed {
     /// Schedules a closure to be run just before the `exec` function is
     /// invoked.
     ///
-    /// This method is stable and usable, but it should be unsafe. To fix
-    /// that, it got deprecated in favor of the unsafe [`pre_exec`].
+    /// `before_exec` used to be a safe method, but it needs to be unsafe since the closure may only
+    /// perform operations that are *async-signal-safe*. Hence it got deprecated in favor of the
+    /// unsafe [`pre_exec`]. Meanwhile, Rust gained the ability to make an existing safe method
+    /// fully unsafe in a new edition, which is how `before_exec` became `unsafe`. It still also
+    /// remains deprecated; `pre_exec` should be used instead.
     ///
     /// [`pre_exec`]: CommandExt::pre_exec
     #[stable(feature = "process_exec", since = "1.15.0")]
     #[deprecated(since = "1.37.0", note = "should be unsafe, use `pre_exec` instead")]
-    fn before_exec<F>(&mut self, f: F) -> &mut process::Command
+    #[cfg_attr(bootstrap, rustc_deprecated_safe_2024)]
+    #[cfg_attr(
+        not(bootstrap),
+        rustc_deprecated_safe_2024(audit_that = "the closure is async-signal-safe")
+    )]
+    unsafe fn before_exec<F>(&mut self, f: F) -> &mut process::Command
     where
         F: FnMut() -> io::Result<()> + Send + Sync + 'static,
     {
diff --git a/tests/ui/rust-2024/unsafe-before_exec.e2024.stderr b/tests/ui/rust-2024/unsafe-before_exec.e2024.stderr
new file mode 100644
index 00000000000..2798ccdefd0
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-before_exec.e2024.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function `before_exec` is unsafe and requires unsafe block
+  --> $DIR/unsafe-before_exec.rs:14:5
+   |
+LL |     cmd.before_exec(|| Ok(()));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/rust-2024/unsafe-before_exec.rs b/tests/ui/rust-2024/unsafe-before_exec.rs
new file mode 100644
index 00000000000..540394da80e
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-before_exec.rs
@@ -0,0 +1,17 @@
+//@ revisions: e2021 e2024
+//@ only-unix
+//@[e2021] edition: 2021
+//@[e2021] check-pass
+//@[e2024] edition: 2024
+//@[e2024] compile-flags: -Zunstable-options
+
+use std::process::Command;
+use std::os::unix::process::CommandExt;
+
+#[allow(deprecated)]
+fn main() {
+    let mut cmd = Command::new("sleep");
+    cmd.before_exec(|| Ok(()));
+    //[e2024]~^ ERROR call to unsafe function `before_exec` is unsafe
+    drop(cmd); // we don't actually run the command.
+}