aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/util.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-08-09 16:22:05 +0200
committerEelco Dolstra <edolstra@gmail.com>2017-08-09 16:22:05 +0200
commitaf765a8eab288eb638100e027b97a1d15e4e3026 (patch)
tree0ab17da6aae1af4c83efef428deae6d0b534aa93 /src/libutil/util.cc
parentc6184dec6c208d39a329586d0503b7a51bc2ded1 (diff)
Use /proc/self/fd to efficiently close all FDs on Linux
Issue #1506.
Diffstat (limited to 'src/libutil/util.cc')
-rw-r--r--src/libutil/util.cc18
1 files changed, 16 insertions, 2 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 27f4fea18..55d3e1d16 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -310,6 +310,7 @@ string readLine(int fd)
while (1) {
checkInterrupt();
char ch;
+ // FIXME: inefficient
ssize_t rd = read(fd, &ch, 1);
if (rd == -1) {
if (errno != EINTR)
@@ -962,11 +963,24 @@ string runProgram(Path program, bool searchPath, const Strings & args,
void closeMostFDs(const set<int> & exceptions)
{
+#if __linux__
+ try {
+ for (auto & s : readDirectory("/proc/self/fd")) {
+ auto fd = std::stoi(s.name);
+ if (!exceptions.count(fd)) {
+ debug("closing leaked FD %d", fd);
+ close(fd);
+ }
+ }
+ return;
+ } catch (SysError &) {
+ }
+#endif
+
int maxFD = 0;
maxFD = sysconf(_SC_OPEN_MAX);
for (int fd = 0; fd < maxFD; ++fd)
- if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO
- && exceptions.find(fd) == exceptions.end())
+ if (!exceptions.count(fd))
close(fd); /* ignore result */
}