From e0a53ed63ab9132b031153d1e69591195e97a59b Mon Sep 17 00:00:00 2001 From: Tomasz Miąsko Date: Sun, 8 May 2022 00:00:00 +0000 Subject: Use `fcntl(fd, F_GETFD)` to detect if standard streams are open In the previous implementation, if the standard streams were open, but the RLIMIT_NOFILE value was below three, the poll would fail with EINVAL: > ERRORS: EINVAL The nfds value exceeds the RLIMIT_NOFILE value. Switch to the existing fcntl based implementation to avoid the issue. --- library/std/src/sys/unix/mod.rs | 37 ++++++------------------------------- 1 file changed, 6 insertions(+), 31 deletions(-) (limited to 'library/std/src/sys/unix/mod.rs') diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 8e909aab7f0..d823e51afa2 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -67,48 +67,23 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) { args::init(argc, argv); unsafe fn sanitize_standard_fds() { - #[cfg(not(miri))] - // The standard fds are always available in Miri. cfg_if::cfg_if! { if #[cfg(not(any( + // The standard fds are always available in Miri. + miri, target_os = "emscripten", target_os = "fuchsia", target_os = "vxworks", - // The poll on Darwin doesn't set POLLNVAL for closed fds. - target_os = "macos", - target_os = "ios", - target_os = "redox", target_os = "l4re", )))] { - use crate::sys::os::errno; - let pfds: &mut [_] = &mut [ - libc::pollfd { fd: 0, events: 0, revents: 0 }, - libc::pollfd { fd: 1, events: 0, revents: 0 }, - libc::pollfd { fd: 2, events: 0, revents: 0 }, - ]; - while libc::poll(pfds.as_mut_ptr(), 3, 0) == -1 { - if errno() == libc::EINTR { - continue; - } - libc::abort(); - } - for pfd in pfds { - if pfd.revents & libc::POLLNVAL == 0 { - continue; - } - if libc::open("/dev/null\0".as_ptr().cast(), 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(); - } - } - } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "redox"))] { use crate::sys::os::errno; for fd in 0..3 { if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF { if libc::open("/dev/null\0".as_ptr().cast(), 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(); } } -- cgit 1.4.1-3-g733a5