diff --git a/meson.build b/meson.build index 4ed8017e..6fc4504a 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 4b87c559..ce6e4c38 100644 --- a/src/libcamera/process.cpp +++ b/src/libcamera/process.cpp @@ -69,6 +69,31 @@ void closeAllFdsExcept(std::vector v) 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;