about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorThe 8472 <git@infinite-source.de>2022-06-04 11:34:02 +0200
committerThe 8472 <git@infinite-source.de>2022-06-04 11:43:02 +0200
commitd3465a8f210403b922d5796b1f24b536f4defedc (patch)
tree0fd35067327633f3c2d43a862dc02153a2c9fef0 /library/std/src
parente0a53ed63ab9132b031153d1e69591195e97a59b (diff)
downloadrust-d3465a8f210403b922d5796b1f24b536f4defedc.tar.gz
rust-d3465a8f210403b922d5796b1f24b536f4defedc.zip
keep using poll as fast path and only use fcntl as fallback
this minimizes the amount of syscalls performed during startup
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/sys/unix/mod.rs83
2 files changed, 65 insertions, 19 deletions
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 6dc3fd98584..55a97be43e2 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -239,6 +239,7 @@
 #![feature(dropck_eyepatch)]
 #![feature(exhaustive_patterns)]
 #![feature(intra_doc_pointers)]
+#![feature(label_break_value)]
 #![feature(lang_items)]
 #![feature(let_chains)]
 #![feature(linkage)]
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index d823e51afa2..0f06811a1d6 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -67,25 +67,70 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
     args::init(argc, argv);
 
     unsafe fn sanitize_standard_fds() {
-        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",
-                target_os = "l4re",
-            )))] {
-                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();
-                        }
+        // fast path with a single syscall for systems with poll()
+        #[cfg(not(any(
+            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",
+        )))]
+        'poll: {
+            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;
+                }
+                if errno() == libc::EINVAL {
+                    // RLIMIT_NOFILE may be preventing use of poll()
+                    break 'poll;
+                }
+                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();
+                }
+            }
+            return;
+        }
+
+        // fallback in case poll isn't available or limited by RLIMIT_NOFILE
+        #[cfg(not(any(
+            // The standard fds are always available in Miri.
+            miri,
+            target_os = "emscripten",
+            target_os = "fuchsia",
+            target_os = "vxworks",
+            target_os = "l4re",
+        )))]
+        {
+            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();
                     }
                 }
             }