Auto merge of #66547 - leo60228:procfs-fallback, r=dtolnay
Fallback to .init_array when no arguments are available on glibc Linux Linux is one of the only platforms where `std::env::args` doesn't work in a cdylib.
This commit is contained in:
commit
3907d59bcf
@ -702,6 +702,11 @@ pub struct ArgsOs { inner: sys::args::Args }
|
||||
/// (such as `*` and `?`). On Windows this is not done, and such arguments are
|
||||
/// passed as-is.
|
||||
///
|
||||
/// On glibc Linux, arguments are retrieved by placing a function in .init_array.
|
||||
/// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension.
|
||||
/// This allows `std::env::args` to work even in a `cdylib` or `staticlib`, as it does on macOS
|
||||
/// and Windows.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// The returned iterator will panic during iteration if any argument to the
|
||||
@ -732,6 +737,11 @@ pub fn args() -> Args {
|
||||
/// set to arbitrary text, and it may not even exist, so this property should
|
||||
/// not be relied upon for security purposes.
|
||||
///
|
||||
/// On glibc Linux, arguments are retrieved by placing a function in .init_array.
|
||||
/// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension.
|
||||
/// This allows `std::env::args` to work even in a `cdylib` or `staticlib`, as it does on macOS
|
||||
/// and Windows.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -72,12 +72,40 @@ mod imp {
|
||||
// acquire this mutex reentrantly!
|
||||
static LOCK: Mutex = Mutex::new();
|
||||
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8) {
|
||||
unsafe fn really_init(argc: isize, argv: *const *const u8) {
|
||||
let _guard = LOCK.lock();
|
||||
ARGC = argc;
|
||||
ARGV = argv;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
|
||||
#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
|
||||
really_init(_argc, _argv);
|
||||
}
|
||||
|
||||
/// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension.
|
||||
/// This allows `std::env::args` to work even in a `cdylib`, as it does on macOS and Windows.
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
#[used]
|
||||
#[link_section = ".init_array.00099"]
|
||||
static ARGV_INIT_ARRAY: extern "C" fn(
|
||||
crate::os::raw::c_int,
|
||||
*const *const u8,
|
||||
*const *const u8,
|
||||
) = {
|
||||
extern "C" fn init_wrapper(
|
||||
argc: crate::os::raw::c_int,
|
||||
argv: *const *const u8,
|
||||
_envp: *const *const u8,
|
||||
) {
|
||||
unsafe {
|
||||
really_init(argc as isize, argv);
|
||||
}
|
||||
}
|
||||
init_wrapper
|
||||
};
|
||||
|
||||
pub unsafe fn cleanup() {
|
||||
let _guard = LOCK.lock();
|
||||
ARGC = 0;
|
||||
|
12
src/test/run-make-fulldeps/glibc-staticlib-args/Makefile
Normal file
12
src/test/run-make-fulldeps/glibc-staticlib-args/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
# only-gnu
|
||||
# only-linux
|
||||
|
||||
-include ../tools.mk
|
||||
|
||||
# This ensures that std::env::args works in a library called from C on glibc Linux.
|
||||
|
||||
all:
|
||||
$(RUSTC) --crate-type=staticlib library.rs
|
||||
$(CC) program.c $(call STATICLIB,library) $(call OUT_EXE,program) \
|
||||
$(EXTRACFLAGS) $(EXTRACXXFLAGS)
|
||||
$(call RUN,program)
|
@ -0,0 +1,4 @@
|
||||
#[no_mangle]
|
||||
pub extern fn args_check() {
|
||||
assert_ne!(std::env::args_os().count(), 0);
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
// ignore-license
|
||||
void args_check();
|
||||
|
||||
int main() {
|
||||
args_check();
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user