about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-12-14 17:17:57 +0100
committerGitHub <noreply@github.com>2022-12-14 17:17:57 +0100
commit6d3a93c82342ee7bbf0b6f90570207bd48653229 (patch)
tree07e6b954ce6cbd71dc4af67a217a03a64f098c06
parentba71a63fde087b5bddd71bc13b95cee4b71da8e2 (diff)
parent3465d5fb168e99fd3a16a6b525feffbeca43647e (diff)
downloadrust-6d3a93c82342ee7bbf0b6f90570207bd48653229.tar.gz
rust-6d3a93c82342ee7bbf0b6f90570207bd48653229.zip
Rollup merge of #105598 - RalfJung:more-comments, r=the8472
explain mem::forget(env_lock) in fork/exec

I stumbled upon this while doing triage for https://github.com/rust-lang/rust/issues/64718.
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs7
1 files changed, 4 insertions, 3 deletions
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 56a805cef73..c0716a089bc 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -66,14 +66,15 @@ impl Command {
         //
         // Note that as soon as we're done with the fork there's no need to hold
         // a lock any more because the parent won't do anything and the child is
-        // in its own process. Thus the parent drops the lock guard while the child
-        // forgets it to avoid unlocking it on a new thread, which would be invalid.
+        // in its own process. Thus the parent drops the lock guard immediately.
+        // The child calls `mem::forget` to leak the lock, which is crucial because
+        // releasing a lock is not async-signal-safe.
         let env_lock = sys::os::env_read_lock();
         let (pid, pidfd) = unsafe { self.do_fork()? };
 
         if pid == 0 {
             crate::panic::always_abort();
-            mem::forget(env_lock);
+            mem::forget(env_lock); // avoid non-async-signal-safe unlocking
             drop(input);
             let Err(err) = unsafe { self.do_exec(theirs, envp.as_ref()) };
             let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32;