Skip to content

Commit 26c9441

Browse files
committed
Close FDs based on /proc/self/fd
... not to waste time with close(2)ing RLIMIT_NOFILE-3 non-existing FDs. Newer kernel = higher RLIMIT_NOFILE = more time wasted refs #8437
1 parent 5f548c8 commit 26c9441

File tree

4 files changed

+67
-28
lines changed

4 files changed

+67
-28
lines changed

icinga-app/icinga.cpp

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -906,24 +906,13 @@ int main(int argc, char **argv)
906906
#ifndef _WIN32
907907
String keepFDs = Utility::GetFromEnvironment("ICINGA2_KEEP_FDS");
908908
if (keepFDs.IsEmpty()) {
909-
rlimit rl;
910-
if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) {
911-
rlim_t maxfds = rl.rlim_max;
912-
913-
if (maxfds == RLIM_INFINITY)
914-
maxfds = 65536;
915-
916-
for (rlim_t i = 3; i < maxfds; i++) {
917-
int rc = close(i);
918-
919909
#ifdef I2_DEBUG
920-
if (rc >= 0)
921-
std::cerr << "Closed FD " << i << " which we inherited from our parent process." << std::endl;
910+
Utility::CloseAllFDs({0, 1, 2}, [](int fd) {
911+
std::cerr << "Closed FD " << fd << " which we inherited from our parent process." << std::endl;
912+
});
922913
#else /* I2_DEBUG */
923-
(void)rc;
914+
Utility::CloseAllFDs({0, 1, 2});
924915
#endif /* I2_DEBUG */
925-
}
926-
}
927916
}
928917
#endif /* _WIN32 */
929918

lib/base/process.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -240,17 +240,7 @@ static void ProcessHandler()
240240
sigfillset(&mask);
241241
sigprocmask(SIG_SETMASK, &mask, nullptr);
242242

243-
rlimit rl;
244-
if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) {
245-
rlim_t maxfds = rl.rlim_max;
246-
247-
if (maxfds == RLIM_INFINITY)
248-
maxfds = 65536;
249-
250-
for (rlim_t i = 3; i < maxfds; i++)
251-
if (i != static_cast<rlim_t>(l_ProcessControlFD))
252-
(void)close(i);
253-
}
243+
Utility::CloseAllFDs({0, 1, 2, l_ProcessControlFD});
254244

255245
for (;;) {
256246
size_t length;

lib/base/utility.cpp

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
#include "base/utility.hpp"
1010
#include "base/json.hpp"
1111
#include "base/objectlock.hpp"
12+
#include <algorithm>
1213
#include <cstdint>
1314
#include <mmatch.h>
14-
#include <boost/filesystem/path.hpp>
15-
#include <boost/filesystem/operations.hpp>
15+
#include <boost/filesystem.hpp>
1616
#include <boost/lexical_cast.hpp>
1717
#include <boost/system/error_code.hpp>
1818
#include <boost/thread/tss.hpp>
@@ -27,6 +27,7 @@
2727
#include <iterator>
2828
#include <stdlib.h>
2929
#include <future>
30+
#include <set>
3031
#include <utf8.h>
3132
#include <vector>
3233

@@ -44,6 +45,7 @@
4445
# include <pwd.h>
4546
# include <grp.h>
4647
# include <errno.h>
48+
# include <unistd.h>
4749
#endif /* _WIN32 */
4850

4951
#ifdef _WIN32
@@ -833,6 +835,61 @@ void Utility::SetCloExec(int fd, bool cloexec)
833835
<< boost::errinfo_errno(errno));
834836
}
835837
}
838+
839+
void Utility::CloseAllFDs(const std::vector<int>& except, std::function<void(int)> onClose)
840+
{
841+
#if defined(__linux__) || defined(__APPLE__)
842+
namespace fs = boost::filesystem;
843+
844+
std::set<int> fds;
845+
846+
#ifdef __linux__
847+
const char *dir = "/proc/self/fd";
848+
#endif /* __linux__ */
849+
#ifdef __APPLE__
850+
const char *dir = "/dev/fd";
851+
#endif /* __APPLE__ */
852+
853+
for (fs::directory_iterator current {fs::path(dir)}, end; current != end; ++current) {
854+
auto entry (current->path().filename());
855+
int fd;
856+
857+
try {
858+
fd = boost::lexical_cast<int>(entry.c_str());
859+
} catch (...) {
860+
continue;
861+
}
862+
863+
fds.emplace(fd);
864+
}
865+
866+
for (auto fd : except) {
867+
fds.erase(fd);
868+
}
869+
870+
for (auto fd : fds) {
871+
if (close(fd) >= 0 && onClose) {
872+
onClose(fd);
873+
}
874+
}
875+
#else /* __linux__ || __APPLE__ */
876+
rlimit rl;
877+
878+
if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) {
879+
rlim_t maxfds = rl.rlim_max;
880+
881+
if (maxfds == RLIM_INFINITY) {
882+
maxfds = 65536;
883+
}
884+
885+
for (int fd = 0; fd < maxfds; ++fd) {
886+
if (std::find(except.begin(), except.end(), fd) == except.end() && close(fd) >= 0 && onClose) {
887+
onClose(fd);
888+
}
889+
}
890+
}
891+
#endif /* __linux__ || __APPLE__ */
892+
}
836893
#endif /* _WIN32 */
837894

838895
void Utility::SetNonBlockingSocket(SOCKET s, bool nb)

lib/base/utility.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "base/array.hpp"
99
#include "base/threadpool.hpp"
1010
#include <boost/thread/tss.hpp>
11+
#include <functional>
1112
#include <typeinfo>
1213
#include <vector>
1314

@@ -80,6 +81,8 @@ class Utility
8081
#ifndef _WIN32
8182
static void SetNonBlocking(int fd, bool nb = true);
8283
static void SetCloExec(int fd, bool cloexec = true);
84+
85+
static void CloseAllFDs(const std::vector<int>& except, std::function<void(int)> onClose = nullptr);
8386
#endif /* _WIN32 */
8487

8588
static void SetNonBlockingSocket(SOCKET s, bool nb = true);

0 commit comments

Comments
 (0)