libutil, libstore: move closeExtraFDs to derivation goal

it's only used there.

Change-Id: I61ee47d37214c59c073cc9ed671ac1c82430227c
This commit is contained in:
eldritch horrors
2026-02-02 14:20:54 +00:00
parent 52590089df
commit 9a31cc7da0
3 changed files with 46 additions and 52 deletions
@@ -1199,6 +1199,52 @@ void LocalDerivationGoal::chownToBuilder(const AutoCloseFD & fd)
throw SysError("cannot change ownership of file '%1%'", fd.guessOrInventPath());
}
static void closeExtraFDs()
{
constexpr int MAX_KEPT_FD = 2;
static_assert(std::max({STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}) == MAX_KEPT_FD);
// Both Linux and FreeBSD support close_range.
#if __linux__ || __FreeBSD__
auto closeRange = [](unsigned int first, unsigned int last, int flags) -> int {
// musl does not have close_range as of 2024-08-10
// patch: https://www.openwall.com/lists/musl/2024/08/01/9
#if HAVE_CLOSE_RANGE
return close_range(first, last, flags);
#else
return syscall(SYS_close_range, first, last, flags);
#endif
};
// 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 (closeRange(3, ~0U, 0) == 0) {
return;
}
#endif
#if __linux__
try {
for (auto & s : readDirectory("/proc/self/fd")) {
auto fd = std::stoi(s.name);
if (fd > MAX_KEPT_FD) {
debug("closing leaked FD %d", fd);
close(fd);
}
}
return;
} catch (SysError &) {
}
#endif
int maxFD = 0;
maxFD = sysconf(_SC_OPEN_MAX);
for (int fd = MAX_KEPT_FD + 1; fd < maxFD; ++fd) {
close(fd); /* ignore result */
}
}
void LocalDerivationGoal::runChild(const Path & builder, const Strings & envStrs, const Strings & args)
{
/* Warning: in the child we should absolutely not make any SQLite
-46
View File
@@ -268,52 +268,6 @@ void Pipe::close()
writeSide.close();
}
void closeExtraFDs()
{
constexpr int MAX_KEPT_FD = 2;
static_assert(std::max({STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}) == MAX_KEPT_FD);
// Both Linux and FreeBSD support close_range.
#if __linux__ || __FreeBSD__
auto closeRange = [](unsigned int first, unsigned int last, int flags) -> int {
// musl does not have close_range as of 2024-08-10
// patch: https://www.openwall.com/lists/musl/2024/08/01/9
#if HAVE_CLOSE_RANGE
return close_range(first, last, flags);
#else
return syscall(SYS_close_range, first, last, flags);
#endif
};
// 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 (closeRange(3, ~0U, 0) == 0) {
return;
}
#endif
#if __linux__
try {
for (auto & s : readDirectory("/proc/self/fd")) {
auto fd = std::stoi(s.name);
if (fd > MAX_KEPT_FD) {
debug("closing leaked FD %d", fd);
close(fd);
}
}
return;
} catch (SysError &) {
}
#endif
int maxFD = 0;
maxFD = sysconf(_SC_OPEN_MAX);
for (int fd = MAX_KEPT_FD + 1; fd < maxFD; ++fd)
close(fd); /* ignore result */
}
void closeOnExec(int fd, bool doClose)
{
int prev;
-6
View File
@@ -101,12 +101,6 @@ private:
SocketPair(AutoCloseFD a, AutoCloseFD b) : a(std::move(a)), b(std::move(b)) {}
};
/**
* Close all file descriptors except stdio fds (ie 0, 1, 2).
* Good practice in child processes.
*/
void closeExtraFDs();
/**
* Set or clear the close-on-exec flag for the given file descriptor.
*/