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

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

Commit Message

Barnabás Pőcze March 25, 2025, 6:08 p.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>
---
 meson.build               |  4 ++++
 src/libcamera/process.cpp | 20 ++++++++++++++++++++
 2 files changed, 24 insertions(+)

Comments

Laurent Pinchart March 26, 2025, 2:44 p.m. UTC | #1
Hi Barnabás,

Thank you for the patch.

On Tue, Mar 25, 2025 at 07:08:20PM +0100, Barnabás Pőcze wrote:
> 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>
> ---
>  meson.build               |  4 ++++
>  src/libcamera/process.cpp | 20 ++++++++++++++++++++
>  2 files changed, 24 insertions(+)
> 
> diff --git a/meson.build b/meson.build
> index 668ec3969..00291d628 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -103,6 +103,10 @@ if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix : '#define _GNU_SOUR
>      config_h.set('HAVE_SECURE_GETENV', 1)
>  endif
>  
> +if cc.has_header_symbol('unistd.h', 'close_range', prefix : '#define _GNU_SOURCE')
> +    config_h.set('HAVE_CLOSE_RANGE', 1)
> +endif
> +

Please move this before HAVE_FILE_SEALS, in alphabetical order.

>  common_arguments = [
>      '-Wmissing-declarations',
>      '-Wshadow',
> diff --git a/src/libcamera/process.cpp b/src/libcamera/process.cpp
> index 01503e485..5fa813300 100644
> --- a/src/libcamera/process.cpp
> +++ b/src/libcamera/process.cpp
> @@ -70,6 +70,26 @@ void closeAllFdsExcept(Span<const int> fds)
>  
>  	ASSERT(v.empty() || v.front() >= 0);
>  
> +#if HAVE_CLOSE_RANGE
> +	static const bool hasCloseRange = [] {
> +		return close_range(~0u, 0, 0) < 0 && errno == EINVAL;
> +	}();

Why do you need to test this ? Is it because we may be running against a
kernel that doesn't provide the system call ? A comment could be useful:

	/*
	 * The close_range() system call was added in Linux v5.11. Perform a
	 * runtime support check, in case we're running on an older kernel.
	 */

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +
> +	if (hasCloseRange) {
> +		unsigned int prev = 0;
> +
> +		for (unsigned int curr : v) {
> +			ASSERT(prev <= curr);
> +			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;

Patch
diff mbox series

diff --git a/meson.build b/meson.build
index 668ec3969..00291d628 100644
--- a/meson.build
+++ b/meson.build
@@ -103,6 +103,10 @@  if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix : '#define _GNU_SOUR
     config_h.set('HAVE_SECURE_GETENV', 1)
 endif
 
+if cc.has_header_symbol('unistd.h', 'close_range', prefix : '#define _GNU_SOURCE')
+    config_h.set('HAVE_CLOSE_RANGE', 1)
+endif
+
 common_arguments = [
     '-Wmissing-declarations',
     '-Wshadow',
diff --git a/src/libcamera/process.cpp b/src/libcamera/process.cpp
index 01503e485..5fa813300 100644
--- a/src/libcamera/process.cpp
+++ b/src/libcamera/process.cpp
@@ -70,6 +70,26 @@  void closeAllFdsExcept(Span<const int> fds)
 
 	ASSERT(v.empty() || v.front() >= 0);
 
+#if HAVE_CLOSE_RANGE
+	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);
+			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;