Skip to content

Commit 15ceb94

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 8b20a13 commit 15ceb94

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: 58 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>
@@ -44,6 +44,7 @@
4444
# include <pwd.h>
4545
# include <grp.h>
4646
# include <errno.h>
47+
# include <unistd.h>
4748
#endif /* _WIN32 */
4849

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

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

lib/base/utility.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include "base/array.hpp"
99
#include "base/threadpool.hpp"
1010
#include <boost/thread/tss.hpp>
11+
#include <functional>
12+
#include <set>
1113
#include <typeinfo>
1214
#include <vector>
1315

@@ -80,6 +82,8 @@ class Utility
8082
#ifndef _WIN32
8183
static void SetNonBlocking(int fd, bool nb = true);
8284
static void SetCloExec(int fd, bool cloexec = true);
85+
86+
static void CloseAllFDs(const std::vector<int>& except, std::function<void(int)> onClose = [](int) {});
8387
#endif /* _WIN32 */
8488

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

0 commit comments

Comments
 (0)