[RFC,v4,8/9] libcamera: process: Use `close_range()` when available
diff mbox series

Message ID 20250424112203.445351-9-barnabas.pocze@ideasonboard.com
State Superseded
Headers show
Series
  • libcamera: process: Remove `ProcessManager` singleton
Related show

Commit Message

Barnabás Pőcze April 24, 2025, 11:22 a.m. UTC
Use the `close_range()` system call when available as it is simpler
and faster than iterating `/proc/self/fd/`.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 meson.build               |  4 ++++
 src/libcamera/process.cpp | 25 +++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

Patch
diff mbox series

diff --git a/meson.build b/meson.build
index e9d6187b3..1525bdf4a 100644
--- a/meson.build
+++ b/meson.build
@@ -74,6 +74,10 @@  cc = meson.get_compiler('c')
 cxx = meson.get_compiler('cpp')
 config_h = configuration_data()
 
+if cc.has_header_symbol('unistd.h', 'close_range', prefix : '#define _GNU_SOURCE')
+    config_h.set('HAVE_CLOSE_RANGE', 1)
+endif
+
 if cc.has_header_symbol('fcntl.h', 'F_ADD_SEALS', prefix : '#define _GNU_SOURCE')
     config_h.set('HAVE_FILE_SEALS', 1)
 endif
diff --git a/src/libcamera/process.cpp b/src/libcamera/process.cpp
index 369fdb12d..42b56374d 100644
--- a/src/libcamera/process.cpp
+++ b/src/libcamera/process.cpp
@@ -70,6 +70,31 @@  void closeAllFdsExcept(Span<const int> fds)
 
 	ASSERT(v.empty() || v.front() >= 0);
 
+#if HAVE_CLOSE_RANGE
+	/*
+	 * At the moment libcamera does not require at least Linux 5.9,
+	 * which introduced the `close_range()` system call, so a runtime
+	 * check is also needed to make sure that it is supported.
+	 */
+	static const bool hasCloseRange = [] {
+		return close_range(~0u, 0, 0) < 0 && errno == EINVAL;
+	}();
+
+	if (hasCloseRange) {
+		unsigned int prev = 0;
+
+		for (unsigned int curr : v) {
+			ASSERT(prev <= curr + 1);
+			if (prev < curr)
+				close_range(prev, curr - 1, 0);
+			prev = curr + 1;
+		}
+
+		close_range(prev, ~0u, 0);
+		return;
+	}
+#endif
+
 	DIR *dir = opendir("/proc/self/fd");
 	if (!dir)
 		return;