1
Fork 0

Rollup merge of #87236 - sunfishcode:avoid-locking-args, r=joshtriplett

Simplify command-line argument initialization on unix

Simplify Rust's command-line argument initialization code on unix:
 - The cleanup code isn't needed, because it was just zeroing out non-owning variables at runtime cleanup time. After 91c3eee173, Rust's command-line initialization code on unix no longer allocates `CString`s and a `Vec` at startup time.
 - The `Mutex` isn't needed; if there's somehow a call to `args()` before argument initialization has happened, the code returns return an empty list, which we can do with a null check.

With these changes, a simple cdylib that doesn't use threads avoids getting `pthread_mutex_lock`/`pthread_mutex_unlock` in its symbol table.
This commit is contained in:
Guillaume Gomez 2021-07-19 11:37:45 +02:00 committed by GitHub
commit 6df9df7e36
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 3 additions and 22 deletions

View file

@ -14,11 +14,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
imp::init(argc, argv) imp::init(argc, argv)
} }
/// One-time global cleanup.
pub unsafe fn cleanup() {
imp::cleanup()
}
/// Returns the command line arguments /// Returns the command line arguments
pub fn args() -> Args { pub fn args() -> Args {
imp::args() imp::args()
@ -82,16 +77,10 @@ mod imp {
use crate::ptr; use crate::ptr;
use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering}; use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering};
use crate::sys_common::mutex::StaticMutex;
static ARGC: AtomicIsize = AtomicIsize::new(0); static ARGC: AtomicIsize = AtomicIsize::new(0);
static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut()); static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
// We never call `ENV_LOCK.init()`, so it is UB to attempt to
// acquire this mutex reentrantly!
static LOCK: StaticMutex = StaticMutex::new();
unsafe fn really_init(argc: isize, argv: *const *const u8) { unsafe fn really_init(argc: isize, argv: *const *const u8) {
let _guard = LOCK.lock();
ARGC.store(argc, Ordering::Relaxed); ARGC.store(argc, Ordering::Relaxed);
ARGV.store(argv as *mut _, Ordering::Relaxed); ARGV.store(argv as *mut _, Ordering::Relaxed);
} }
@ -127,21 +116,16 @@ mod imp {
init_wrapper init_wrapper
}; };
pub unsafe fn cleanup() {
let _guard = LOCK.lock();
ARGC.store(0, Ordering::Relaxed);
ARGV.store(ptr::null_mut(), Ordering::Relaxed);
}
pub fn args() -> Args { pub fn args() -> Args {
Args { iter: clone().into_iter() } Args { iter: clone().into_iter() }
} }
fn clone() -> Vec<OsString> { fn clone() -> Vec<OsString> {
unsafe { unsafe {
let _guard = LOCK.lock(); // Load ARGC and ARGV without a lock. If the store to either ARGV or
let argc = ARGC.load(Ordering::Relaxed); // ARGC isn't visible yet, we'll return an empty argument list.
let argv = ARGV.load(Ordering::Relaxed); let argv = ARGV.load(Ordering::Relaxed);
let argc = if argv.is_null() { 0 } else { ARGC.load(Ordering::Relaxed) };
(0..argc) (0..argc)
.map(|i| { .map(|i| {
let cstr = CStr::from_ptr(*argv.offset(i) as *const libc::c_char); let cstr = CStr::from_ptr(*argv.offset(i) as *const libc::c_char);
@ -159,8 +143,6 @@ mod imp {
pub unsafe fn init(_argc: isize, _argv: *const *const u8) {} pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
pub fn cleanup() {}
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub fn args() -> Args { pub fn args() -> Args {
use crate::os::unix::prelude::*; use crate::os::unix::prelude::*;

View file

@ -123,7 +123,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
// SAFETY: must be called only once during runtime cleanup. // SAFETY: must be called only once during runtime cleanup.
// NOTE: this is not guaranteed to run, for example when the program aborts. // NOTE: this is not guaranteed to run, for example when the program aborts.
pub unsafe fn cleanup() { pub unsafe fn cleanup() {
args::cleanup();
stack_overflow::cleanup(); stack_overflow::cleanup();
} }