diff --git a/include/boost/process/v1/detail/posix/handles.hpp b/include/boost/process/v1/detail/posix/handles.hpp index bd1b498e4..88b26f69b 100644 --- a/include/boost/process/v1/detail/posix/handles.hpp +++ b/include/boost/process/v1/detail/posix/handles.hpp @@ -133,7 +133,9 @@ struct limit_handles_ : handler_base_ext if (std::find(used_handles.begin(), used_handles.end(), conv) != used_handles.end()) continue; - if (::close(conv) != 0) + int error; + while ((error = ::close(conv)) == -1 && errno == EINTR); + if (error == -1 && errno != EBADF) { exec.set_error(::boost::process::v1::detail::get_last_error(), "close() failed"); return; diff --git a/src/posix/close_handles.cpp b/src/posix/close_handles.cpp index 5795a3b1c..8de6a8978 100644 --- a/src/posix/close_handles.cpp +++ b/src/posix/close_handles.cpp @@ -24,12 +24,20 @@ // // gives us // -// int closefrom(int fd); +// void closefrom(int lowfd); // int close_range(u_int lowfd, u_int highfd, int flags); #include #define BOOST_PROCESS_V2_HAS_CLOSE_RANGE_AND_CLOSEFROM 1 +#elif defined(__OpenBSD__) + +// https://man.openbsd.org/closefrom.2 +// int closefrom(int fd); + +#include +#define BOOST_PROCESS_V2_HAS_CLOSEFROM_WITH_ERRNO 1 + #elif defined(__sun) /*https://docs.oracle.com/cd/E36784_01/html/E36874/closefrom-3c.html @@ -113,6 +121,36 @@ void close_all(const std::vector & whitelist, error_code & ec) ec = BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error(); } +#elif defined(BOOST_PROCESS_V2_HAS_CLOSEFROM_WITH_ERRNO) + +// OpenBSD impl - whitelist must be ordered +void close_all(const std::vector & whitelist, error_code & /*ec*/) +{ + //the most common scenario is whitelist = {0,1,2} + if (!whitelist.empty()) + { + if (whitelist.front() != 0) { + for (int fd = 0; fd < whitelist.front(); fd++) + while (::close(fd) == -1 && errno == EINTR); + } + for (std::size_t idx = 0u; + idx < (whitelist.size() - 1u); + idx++) + { + const auto mine = whitelist[idx]; + const auto next = whitelist[idx + 1]; + if ((mine + 1) != next && (mine != next)) + { + for (int fd = mine + 1; fd < next; fd++) + while (::close(fd) == -1 && errno == EINTR); + } + } + while (::closefrom(whitelist.back() + 1) == -1 && errno == EINTR); + } + else + while (::closefrom(0) == -1 && errno == EINTR); +} + #elif defined(BOOST_PROCESS_V2_HAS_CLOSE_RANGE_AND_CLOSEFROM) // freeBSD impl - whitelist must be ordered