[vte] lib: Check for close_range function and use it when available



commit ebecf6ac04488d0d697c255d582ea891c3bf1577
Author: Christian Persch <chpe src gnome org>
Date:   Sun Nov 7 13:38:23 2021 +0100

    lib: Check for close_range function and use it when available
    
    This should enable using close_range also on non-linux platforms that
    do have close_range, e.g. freebsd and (soon) hurd.
    
    Part of https://gitlab.gnome.org/GNOME/vte/-/issues/2528 .

 meson.build    |  7 +++++++
 src/missing.cc | 29 +++++++++--------------------
 src/missing.hh | 11 +++++++++++
 src/spawn.cc   | 12 ++++++++++++
 4 files changed, 39 insertions(+), 20 deletions(-)
---
diff --git a/meson.build b/meson.build
index 09607052..93b7f376 100644
--- a/meson.build
+++ b/meson.build
@@ -325,6 +325,13 @@ check_functions = [
      [],
      false,
   ],
+  [
+    'close_range',
+    'int (*func)(unsigned int, unsigned int, int)',
+     ['unistd.h'],
+     [],
+     false,
+   ],
 
   # Math functions
 
diff --git a/src/missing.cc b/src/missing.cc
index 536b1e03..b5a0742e 100644
--- a/src/missing.cc
+++ b/src/missing.cc
@@ -134,17 +134,17 @@ getrlimit_NOFILE_max(void)
         return RLIM_INFINITY;
 }
 
-#ifdef __linux__
+#ifndef HAVE_CLOSE_RANGE
 
-static inline int
-_vte_close_range(int first_fd,
-                 int last_fd,
-                 unsigned flags)
+int
+close_range(unsigned int first_fd,
+            unsigned int last_fd,
+            unsigned int flags)
 {
-#ifdef SYS_close_range
+#if defined(__linux__) && defined(SYS_close_range)
         return syscall(SYS_close_range,
-                       unsigned(first_fd),
-                       last_fd == -1 ? ~0u : unsigned(last_fd),
+                       first_fd,
+                       last_fd == unsigned(-1) ? ~0u : last_fd,
                        flags);
 #else
         errno = ENOSYS;
@@ -152,7 +152,7 @@ _vte_close_range(int first_fd,
 #endif
 }
 
-#endif /* __linux__ */
+#endif /* !HAVE_CLOSE_RANGE */
 
 /* This function is called between fork and execve/_exit and so must be
  * async-signal-safe; see man:signal-safety(7).
@@ -170,17 +170,6 @@ fdwalk(int (*cb)(void *data, int fd),
 
 #ifdef __linux__
 
-  /* First, try close_range(CLOEXEC) which is faster than the methods
-   * below, and works even if /proc is not available.
-   */
-  res = _vte_close_range(0, -1, CLOSE_RANGE_CLOEXEC);
-  if (res == 0)
-          return 0;
-  if (res == -1 &&
-      errno != ENOSYS /* old kernel */ &&
-      errno != EINVAL /* flags not supported */)
-          return res;
-
   /* Fall back to iterating over /proc/self/fd.
    * Avoid use of opendir/closedir since these are not async-signal-safe.
    */
diff --git a/src/missing.hh b/src/missing.hh
index 7902e41e..0d92f4c7 100644
--- a/src/missing.hh
+++ b/src/missing.hh
@@ -21,12 +21,17 @@
 
 #include <csignal>
 #include <fcntl.h>
+#include <unistd.h>
 
 #ifdef __linux__
 
 #include <sys/ioctl.h>
 #include <sys/syscall.h>
 
+#if __has_include(<linux/close_range.h>)
+#include <linux/close_range.h>
+#endif
+
 #if defined(__mips__) || defined(__mips64__)
 #include <asm/sgidefs.h>
 #endif
@@ -48,6 +53,12 @@ char* strchrnul(char const* s,
                 int c);
 #endif
 
+#ifndef HAVE_CLOSE_RANGE
+int close_range(unsigned int first,
+                unsigned int last,
+                unsigned int flags);
+#endif
+
 #ifdef __linux__
 
 /* BEGIN
diff --git a/src/spawn.cc b/src/spawn.cc
index a0d706cd..fd0ec654 100644
--- a/src/spawn.cc
+++ b/src/spawn.cc
@@ -68,6 +68,18 @@ set_cloexec_cb(void* data,
 static int
 cloexec_from(int fd)
 {
+        /* First, try close_range(CLOEXEC) which is faster than the methods
+         * below, and works even if /proc is not available.
+         */
+        auto const res = close_range(fd, -1, CLOSE_RANGE_CLOEXEC);
+        if (res == 0)
+                return 0;
+        if (res == -1 &&
+            errno != ENOSYS /* old kernel, or not supported on this platform */ &&
+            errno != EINVAL /* flags not supported */)
+                return res;
+
+        /* Fall back to fdwalk */
         return fdwalk(set_cloexec_cb, &fd);
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]