Merge pull request #8442 from Icinga/bugfix/close-ebadf-8437

Close FDs based on /proc/self/fd
This commit is contained in:
Alexander Aleksandrovič Klimov 2021-01-13 10:59:15 +01:00 committed by GitHub
commit 5a0118c6d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 28 deletions

View File

@ -906,24 +906,13 @@ int main(int argc, char **argv)
#ifndef _WIN32
String keepFDs = Utility::GetFromEnvironment("ICINGA2_KEEP_FDS");
if (keepFDs.IsEmpty()) {
rlimit rl;
if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) {
rlim_t maxfds = rl.rlim_max;
if (maxfds == RLIM_INFINITY)
maxfds = 65536;
for (rlim_t i = 3; i < maxfds; i++) {
int rc = close(i);
#ifdef I2_DEBUG
if (rc >= 0)
std::cerr << "Closed FD " << i << " which we inherited from our parent process." << std::endl;
Utility::CloseAllFDs({0, 1, 2}, [](int fd) {
std::cerr << "Closed FD " << fd << " which we inherited from our parent process." << std::endl;
});
#else /* I2_DEBUG */
(void)rc;
Utility::CloseAllFDs({0, 1, 2});
#endif /* I2_DEBUG */
}
}
}
#endif /* _WIN32 */

View File

@ -240,17 +240,7 @@ static void ProcessHandler()
sigfillset(&mask);
sigprocmask(SIG_SETMASK, &mask, nullptr);
rlimit rl;
if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) {
rlim_t maxfds = rl.rlim_max;
if (maxfds == RLIM_INFINITY)
maxfds = 65536;
for (rlim_t i = 3; i < maxfds; i++)
if (i != static_cast<rlim_t>(l_ProcessControlFD))
(void)close(i);
}
Utility::CloseAllFDs({0, 1, 2, l_ProcessControlFD});
for (;;) {
size_t length;

View File

@ -9,10 +9,10 @@
#include "base/utility.hpp"
#include "base/json.hpp"
#include "base/objectlock.hpp"
#include <algorithm>
#include <cstdint>
#include <mmatch.h>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/system/error_code.hpp>
#include <boost/thread/tss.hpp>
@ -27,6 +27,7 @@
#include <iterator>
#include <stdlib.h>
#include <future>
#include <set>
#include <utf8.h>
#include <vector>
@ -44,6 +45,7 @@
# include <pwd.h>
# include <grp.h>
# include <errno.h>
# include <unistd.h>
#endif /* _WIN32 */
#ifdef _WIN32
@ -833,6 +835,61 @@ void Utility::SetCloExec(int fd, bool cloexec)
<< boost::errinfo_errno(errno));
}
}
void Utility::CloseAllFDs(const std::vector<int>& except, std::function<void(int)> onClose)
{
#if defined(__linux__) || defined(__APPLE__)
namespace fs = boost::filesystem;
std::set<int> fds;
#ifdef __linux__
const char *dir = "/proc/self/fd";
#endif /* __linux__ */
#ifdef __APPLE__
const char *dir = "/dev/fd";
#endif /* __APPLE__ */
for (fs::directory_iterator current {fs::path(dir)}, end; current != end; ++current) {
auto entry (current->path().filename());
int fd;
try {
fd = boost::lexical_cast<int>(entry.c_str());
} catch (...) {
continue;
}
fds.emplace(fd);
}
for (auto fd : except) {
fds.erase(fd);
}
for (auto fd : fds) {
if (close(fd) >= 0 && onClose) {
onClose(fd);
}
}
#else /* __linux__ || __APPLE__ */
rlimit rl;
if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) {
rlim_t maxfds = rl.rlim_max;
if (maxfds == RLIM_INFINITY) {
maxfds = 65536;
}
for (int fd = 0; fd < maxfds; ++fd) {
if (std::find(except.begin(), except.end(), fd) == except.end() && close(fd) >= 0 && onClose) {
onClose(fd);
}
}
}
#endif /* __linux__ || __APPLE__ */
}
#endif /* _WIN32 */
void Utility::SetNonBlockingSocket(SOCKET s, bool nb)

View File

@ -8,6 +8,7 @@
#include "base/array.hpp"
#include "base/threadpool.hpp"
#include <boost/thread/tss.hpp>
#include <functional>
#include <typeinfo>
#include <vector>
@ -80,6 +81,8 @@ public:
#ifndef _WIN32
static void SetNonBlocking(int fd, bool nb = true);
static void SetCloExec(int fd, bool cloexec = true);
static void CloseAllFDs(const std::vector<int>& except, std::function<void(int)> onClose = nullptr);
#endif /* _WIN32 */
static void SetNonBlockingSocket(SOCKET s, bool nb = true);