From 1552936bc9e77d19ddcebb931b807c0a0831ead2 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 11 Nov 2021 08:56:42 -0500 Subject: [PATCH] [dontmerge]: Change `setenv` on Linux to panic if threaded See this thread https://internals.rust-lang.org/t/synchronized-ffi-access-to-posix-environment-variable-functions/ My main goal here is to have this go through all of Rust's CI and see if any panics turn up. There are a variety of `set_env()` calls, but AFAICS they are all early in main. Then if that works, I'd like to do a crater run so we can gauge the fallout in the ecosystem of how many places need to be fixed for this. (I think we should introduce `try_set_env()`, but this will still help us understand the fallout) --- library/std/src/sys/unix/os.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 87893d269120b..49b60063b7f98 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -543,7 +543,21 @@ pub fn getenv(k: &OsStr) -> Option { } } +fn process_is_threaded() -> bool { + if cfg!(any(target_os = "linux", target_os = "android")) { + if let Ok(r) = crate::fs::read_dir("/proc/self/task") { + return r.count() > 1; + } + } + // Generic fall through + false +} + pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + if process_is_threaded() { + panic!("Tried to setenv '{:?}' while process has multiple threads", k); + } + let k = CString::new(k.as_bytes())?; let v = CString::new(v.as_bytes())?; @@ -554,6 +568,9 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { } pub fn unsetenv(n: &OsStr) -> io::Result<()> { + if process_is_threaded() { + panic!("Tried to unsetenv '{:?}' while process has multiple threads", n); + } let nbuf = CString::new(n.as_bytes())?; unsafe {