Skip to content

Commit c7c356a

Browse files
luke-jrlaanwj
andcommitted
cpp-subprocess: Iterate through /proc/self/fd for close_fds option on Linux
As an optimization, iterate through /proc/<pid>/fd on Linux. Co-authored-by: laanwj <126646+laanwj@users.noreply.github.com>
1 parent 4f5e04d commit c7c356a

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

src/util/subprocess.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ Documentation for C++ subprocessing library.
3636
#ifndef BITCOIN_UTIL_SUBPROCESS_H
3737
#define BITCOIN_UTIL_SUBPROCESS_H
3838

39+
#include <util/fs.h>
40+
#include <util/strencodings.h>
3941
#include <util/syserror.h>
4042

4143
#include <algorithm>
@@ -1302,13 +1304,37 @@ namespace detail {
13021304

13031305
// Close all the inherited fd's except the error write pipe
13041306
if (parent_->close_fds_) {
1307+
// If possible, try to get the list of open file descriptors from the
1308+
// operating system. This is more efficient, but not guaranteed to be
1309+
// available.
1310+
#ifdef __linux__
1311+
// For Linux, enumerate /proc/<pid>/fd.
1312+
try {
1313+
std::vector<int> fds_to_close;
1314+
for (const auto& it : fs::directory_iterator(strprintf("/proc/%d/fd", getpid()))) {
1315+
auto fd{ToIntegral<uint64_t>(it.path().filename().native())};
1316+
if (!fd || *fd > std::numeric_limits<int>::max()) continue;
1317+
if (*fd <= 2) continue; // leave std{in,out,err} alone
1318+
if (*fd == static_cast<uint64_t>(err_wr_pipe_)) continue;
1319+
fds_to_close.push_back(*fd);
1320+
}
1321+
for (const int fd : fds_to_close) {
1322+
close(fd);
1323+
}
1324+
} catch (const fs::filesystem_error &e) {
1325+
throw OSError("/proc/<pid>/fd iteration failed", e.code().value());
1326+
}
1327+
#else
1328+
// On other operating systems, iterate over all file descriptor slots
1329+
// and try to close them all.
13051330
int max_fd = sysconf(_SC_OPEN_MAX);
13061331
if (max_fd == -1) throw OSError("sysconf failed", errno);
13071332

13081333
for (int i = 3; i < max_fd; i++) {
13091334
if (i == err_wr_pipe_) continue;
13101335
close(i);
13111336
}
1337+
#endif
13121338
}
13131339

13141340
// Replace the current image with the executable

0 commit comments

Comments
 (0)