diff --git a/configure.ac b/configure.ac index 5c22ed17636..198198dea26 100644 --- a/configure.ac +++ b/configure.ac @@ -86,7 +86,7 @@ static char buf[1024];]], AC_LANG_POP(C++) -AC_CHECK_FUNCS([statvfs pipe2]) +AC_CHECK_FUNCS([statvfs pipe2 close_range]) # Check for lutimes, optionally used for changing the mtime of diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 8552c4c9dad..b02ddd53adc 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -28,6 +28,7 @@ subdir('build-utils-meson/subprojects') # HAVE_LUTIMES 1`. The `#define` is unconditional, 0 for not found and 1 # for found. One therefore uses it with `#if` not `#ifdef`. check_funcs = [ + 'close_range', # Optionally used for changing the mtime of symlinks. 'lutimes', # Optionally used for creating pipes on Unix diff --git a/src/libutil/unix/file-descriptor.cc b/src/libutil/unix/file-descriptor.cc index a3af1623fc9..0adf8de1555 100644 --- a/src/libutil/unix/file-descriptor.cc +++ b/src/libutil/unix/file-descriptor.cc @@ -120,8 +120,37 @@ void Pipe::create() ////////////////////////////////////////////////////////////////////// +<<<<<<< HEAD void unix::closeMostFDs(const std::set & exceptions) { +======= +#if __linux__ || __FreeBSD__ +static int unix_close_range(unsigned int first, unsigned int last, int flags) +{ +#if !HAVE_CLOSE_RANGE + return syscall(SYS_close_range, first, last, (unsigned int)flags); +#else + return close_range(first, last, flags); +#endif +} +#endif + +void unix::closeExtraFDs() +{ + constexpr int MAX_KEPT_FD = 2; + static_assert(std::max({STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}) == MAX_KEPT_FD); + +#if __linux__ || __FreeBSD__ + // first try to close_range everything we don't care about. if this + // returns an error with these parameters we're running on a kernel + // that does not implement close_range (i.e. pre 5.9) and fall back + // to the old method. we should remove that though, in some future. + if (unix_close_range(MAX_KEPT_FD + 1, ~0U, 0) == 0) { + return; + } +#endif + +>>>>>>> 5c87c40a5 (Use close_range when available) #if __linux__ try { for (auto & s : std::filesystem::directory_iterator{"/proc/self/fd"}) {