Skip to content

Commit fa1271d

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 b06ea2b commit fa1271d

File tree

3 files changed

+90
-27
lines changed

3 files changed

+90
-27
lines changed

icinga-app/icinga.cpp

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -906,24 +906,14 @@ 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-
909+
Utility::CloseAllFDs<3>(
910+
{0, 1, 2}
919911
#ifdef I2_DEBUG
920-
if (rc >= 0)
921-
std::cerr << "Closed FD " << i << " which we inherited from our parent process." << std::endl;
922-
#else /* I2_DEBUG */
923-
(void)rc;
924-
#endif /* I2_DEBUG */
912+
, [](int fd) {
913+
std::cerr << "Closed FD " << fd << " which we inherited from our parent process." << std::endl;
925914
}
926-
}
915+
#endif /* I2_DEBUG */
916+
);
927917
}
928918
#endif /* _WIN32 */
929919

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<4>({0, 1, 2, l_ProcessControlFD});
254244

255245
for (;;) {
256246
size_t length;

lib/base/utility.hpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,19 @@
77
#include "base/string.hpp"
88
#include "base/array.hpp"
99
#include "base/threadpool.hpp"
10+
#include <array>
11+
#include <boost/filesystem.hpp>
12+
#include <boost/lexical_cast.hpp>
1013
#include <boost/thread/tss.hpp>
14+
#include <cstddef>
15+
#include <set>
1116
#include <typeinfo>
1217
#include <vector>
1318

19+
#ifndef _WIN32
20+
#include <unistd.h>
21+
#endif /* _WIN32 */
22+
1423
namespace icinga
1524
{
1625

@@ -80,6 +89,14 @@ class Utility
8089
#ifndef _WIN32
8190
static void SetNonBlocking(int fd, bool nb = true);
8291
static void SetCloExec(int fd, bool cloexec = true);
92+
93+
template<size_t exceptAmount>
94+
static inline
95+
void CloseAllFDs(const std::array<int, exceptAmount>& except);
96+
97+
template<size_t exceptAmount, class OnClose>
98+
static inline
99+
void CloseAllFDs(const std::array<int, exceptAmount>& except, OnClose onClose);
83100
#endif /* _WIN32 */
84101

85102
static void SetNonBlockingSocket(SOCKET s, bool nb = true);
@@ -157,6 +174,72 @@ class Utility
157174
static boost::thread_specific_ptr<unsigned int> m_RandSeed;
158175
};
159176

177+
#ifndef _WIN32
178+
template<size_t exceptAmount>
179+
inline void Utility::CloseAllFDs(const std::array<int, exceptAmount>& except)
180+
{
181+
CloseAllFDs(except, [](int) {});
182+
}
183+
184+
template<size_t exceptAmount, class OnClose>
185+
inline void Utility::CloseAllFDs(const std::array<int, exceptAmount>& except, OnClose onClose)
186+
{
187+
#if defined(__linux__) || defined(__APPLE__)
188+
namespace fs = boost::filesystem;
189+
190+
std::set<int> fds;
191+
192+
for (fs::directory_iterator current (fs::path(
193+
#ifdef __linux__
194+
"/proc/self/fd"
195+
#endif /* __linux__ */
196+
#ifdef __APPLE__
197+
"/dev/fd"
198+
#endif /* __APPLE__ */
199+
)), end; current != end; ++current) {
200+
auto entry (current->path().filename());
201+
int fd;
202+
203+
try {
204+
fd = boost::lexical_cast<int>(entry.c_str());
205+
} catch (...) {
206+
continue;
207+
}
208+
209+
fds.emplace(fd);
210+
}
211+
212+
for (auto fd : except) {
213+
fds.erase(fd);
214+
}
215+
216+
for (auto fd : fds) {
217+
if (close(fd) >= 0) {
218+
onClose(fd);
219+
}
220+
}
221+
#else /* __linux__ || __APPLE__ */
222+
rlimit rl;
223+
224+
if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) {
225+
rlim_t maxfds = rl.rlim_max;
226+
227+
if (maxfds == RLIM_INFINITY) {
228+
maxfds = 65536;
229+
}
230+
231+
std::set<int> fds (except.begin(), except.end());
232+
233+
for (int fd = 0; fd < maxfds; ++fd) {
234+
if (fds.find(fd) == fds.end() && close(fd) >= 0) {
235+
onClose(fd);
236+
}
237+
}
238+
}
239+
#endif /* __linux__ || __APPLE__ */
240+
}
241+
#endif /* _WIN32 */
242+
160243
}
161244

162245
#endif /* UTILITY_H */

0 commit comments

Comments
 (0)