[vte/wip/close-range] spawn: Use close_range to set CLOEXEC on all FDs




commit 9d3832fd20e8d945538bc699936d7d8361ca2c2b
Author: Christian Persch <chpe src gnome org>
Date:   Thu Dec 24 13:51:28 2020 +0100

    spawn: Use close_range to set CLOEXEC on all FDs
    
    ... when available; otherwise fall back to iterating over /proc/self/fd
    as previously.

 src/missing.cc | 17 ++++++++++++++++-
 src/missing.hh | 16 ++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletion(-)
---
diff --git a/src/missing.cc b/src/missing.cc
index 214419fc..f8320d9a 100644
--- a/src/missing.cc
+++ b/src/missing.cc
@@ -149,7 +149,22 @@ fdwalk(int (*cb)(void *data, int fd),
   int res = 0;
 
 #ifdef __linux__
-  /* Avoid use of opendir/closedir since these are not async-signal-safe. */
+
+  /* First, try close_range(CLOEXEC) which is faster than the methods
+   * below, and works even if /proc is not available.
+   */
+  errno = 0;
+  res = syscall(SYS_close_range, 0u, ~0u, 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.
+   */
   int dir_fd = open ("/proc/self/fd", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
   if (dir_fd >= 0)
     {
diff --git a/src/missing.hh b/src/missing.hh
index 07422708..1d1fdb61 100644
--- a/src/missing.hh
+++ b/src/missing.hh
@@ -33,3 +33,19 @@ int fdwalk(int (*cb)(void* data, int fd),
 char* strchrnul(char const* s,
                 int c);
 #endif
+
+#ifdef __linux__
+
+#ifndef SYS_close_range
+#ifdef __NR_close_range
+#define SYS_close_range __NR_close_range
+#else
+#define SYS_close_range 436
+#endif
+#endif
+
+#ifndef CLOSE_RANGE_CLOEXEC
+#define CLOSE_RANGE_CLOEXEC (1u << 2)
+#endif
+
+#endif /* __linux__ */


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