From 623ba816fa650234b416947d21c7418e435262ae Mon Sep 17 00:00:00 2001 From: Tilghman Lesher Date: Fri, 30 Apr 2010 06:19:35 +0000 Subject: Don't allow file descriptors to go above 64k, when we're closing them in a fork(2). This saves time, when, even though the system allows the process limit to be that high, the practical limit is much lower. Also introduce an additional optimization, in the form of using the CLOEXEC flag to close descriptors at the right time. (closes issue #17223) Reported by: dbackeberg Patches: 20100423__issue17223.diff.txt uploaded by tilghman (license 14) Tested by: dbackeberg git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@260292 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- main/strcompat.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'main/strcompat.c') diff --git a/main/strcompat.c b/main/strcompat.c index b1d8b0d1d..923e935f7 100644 --- a/main/strcompat.c +++ b/main/strcompat.c @@ -26,6 +26,8 @@ #include /* for getrlimit(2) */ #include /* for opendir(3) */ #include /* for opendir(3) */ +#include /* for fcntl(2) */ +#include /* for fcntl(2) */ #ifndef HAVE_STRSEP char *strsep(char **str, const char *delims) @@ -420,14 +422,44 @@ void closefrom(int n) continue; } if ((x = strtol(entry->d_name, &result, 10)) && x >= n) { +#ifdef STRICT_COMPAT close(x); +#else + /* This isn't strictly compatible, but it's actually faster + * for our purposes to set the CLOEXEC flag than to close + * file descriptors. + */ + long flags = fcntl(x, F_GETFD); + if (flags == -1 && errno == EBADF) { + continue; + } + fcntl(x, F_SETFD, flags | FD_CLOEXEC); +#endif } } closedir(dir); } else { getrlimit(RLIMIT_NOFILE, &rl); + if (rl.rlim_cur > 65535) { + /* A more reasonable value. Consider that the primary source of + * file descriptors in Asterisk are UDP sockets, of which we are + * limited to 65,535 per address. We additionally limit that down + * to about 10,000 sockets per protocol. While the kernel will + * allow us to set the fileno limit higher (up to 4.2 billion), + * there really is no practical reason for it to be that high. + */ + rl.rlim_cur = 65535; + } for (x = n; x < rl.rlim_cur; x++) { +#ifdef STRICT_COMPAT close(x); +#else + long flags = fcntl(x, F_GETFD); + if (flags == -1 && errno == EBADF) { + continue; + } + fcntl(x, F_SETFD, flags | FD_CLOEXEC); +#endif } } } -- cgit v1.2.3