@@ -36,6 +36,8 @@ Documentation for C++ subprocessing library.
36
36
#ifndef BITCOIN_UTIL_SUBPROCESS_H
37
37
#define BITCOIN_UTIL_SUBPROCESS_H
38
38
39
+ #include < util/fs.h>
40
+ #include < util/strencodings.h>
39
41
#include < util/syserror.h>
40
42
41
43
#include < algorithm>
@@ -1302,13 +1304,37 @@ namespace detail {
1302
1304
1303
1305
// Close all the inherited fd's except the error write pipe
1304
1306
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.
1305
1330
int max_fd = sysconf (_SC_OPEN_MAX);
1306
1331
if (max_fd == -1 ) throw OSError (" sysconf failed" , errno);
1307
1332
1308
1333
for (int i = 3 ; i < max_fd; i++) {
1309
1334
if (i == err_wr_pipe_) continue ;
1310
1335
close (i);
1311
1336
}
1337
+ #endif
1312
1338
}
1313
1339
1314
1340
// Replace the current image with the executable
0 commit comments