diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index c0b56d8d2b28a..ebfc92ebfeee0 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -61,6 +61,30 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { } unsafe fn sanitize_standard_fds() { + #[allow(dead_code, unused_variables, unused_mut)] + let mut opened_devnull = -1; + #[allow(dead_code, unused_variables, unused_mut)] + let mut open_devnull = || { + #[cfg(not(all(target_os = "linux", target_env = "gnu")))] + use libc::open; + #[cfg(all(target_os = "linux", target_env = "gnu"))] + use libc::open64 as open; + + if opened_devnull != -1 { + if libc::dup(opened_devnull) != -1 { + return; + } + } + opened_devnull = open(c"/dev/null".as_ptr(), libc::O_RDWR, 0); + if opened_devnull == -1 { + // If the stream is closed but we failed to reopen it, abort the + // process. Otherwise we wouldn't preserve the safety of + // operations on the corresponding Rust object Stdin, Stdout, or + // Stderr. + libc::abort(); + } + }; + // fast path with a single syscall for systems with poll() #[cfg(not(any( miri, @@ -76,11 +100,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_vendor = "apple", )))] 'poll: { - #[cfg(not(all(target_os = "linux", target_env = "gnu")))] - use libc::open as open64; - #[cfg(all(target_os = "linux", target_env = "gnu"))] - use libc::open64; - use crate::sys::os::errno; let pfds: &mut [_] = &mut [ libc::pollfd { fd: 0, events: 0, revents: 0 }, @@ -108,13 +127,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { if pfd.revents & libc::POLLNVAL == 0 { continue; } - if open64(c"/dev/null".as_ptr(), libc::O_RDWR, 0) == -1 { - // If the stream is closed but we failed to reopen it, abort the - // process. Otherwise we wouldn't preserve the safety of - // operations on the corresponding Rust object Stdin, Stdout, or - // Stderr. - libc::abort(); - } + open_devnull(); } return; } @@ -131,21 +144,10 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_os = "vita", )))] { - #[cfg(not(all(target_os = "linux", target_env = "gnu")))] - use libc::open as open64; - #[cfg(all(target_os = "linux", target_env = "gnu"))] - use libc::open64; - use crate::sys::os::errno; for fd in 0..3 { if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF { - if open64(c"/dev/null".as_ptr(), libc::O_RDWR, 0) == -1 { - // If the stream is closed but we failed to reopen it, abort the - // process. Otherwise we wouldn't preserve the safety of - // operations on the corresponding Rust object Stdin, Stdout, or - // Stderr. - libc::abort(); - } + open_devnull(); } } }