diff options
author | Werner Koch <wk@gnupg.org> | 2016-07-13 15:33:41 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2016-07-13 15:33:41 +0200 |
commit | e64f9a4af5a379f5a9fde59f0f944cd10ccfc6ea (patch) | |
tree | b1517dddef7a9ceab7594c039033a3b990e8a14c | |
parent | 70bb71e51462e9d81eff80ef8308cd8e15ea96ca (diff) | |
download | libassuan-e64f9a4af5a379f5a9fde59f0f944cd10ccfc6ea.tar.gz |
Speedup closing fds before an exec.
* src/system-posix.c [__linux__]: Include dirent.h.
(get_max_fds) [__linux__]: Return the actual used highest fd.
--
This is the same code as introduced with the
GnuPG commit 512c56af43027149e8beacf259746b8d7bf9b1a2
Signed-off-by: Werner Koch <wk@gnupg.org>
-rw-r--r-- | src/system-posix.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/src/system-posix.c b/src/system-posix.c index 8ca27e6..52376da 100644 --- a/src/system-posix.c +++ b/src/system-posix.c @@ -36,6 +36,9 @@ # include <sys/time.h> # include <sys/resource.h> #endif /*HAVE_GETRLIMIT*/ +#if __linux__ +# include <dirent.h> +#endif /*__linux__ */ #include "assuan-defs.h" @@ -180,6 +183,43 @@ get_max_fds (void) #ifdef HAVE_GETRLIMIT struct rlimit rl; + /* Under Linux we can figure out the highest used file descriptor by + * reading /proc/PID/fd. This is in the common cases much faster + * than for example doing 4096 close calls where almost all of them + * will fail. We use the same code in GnuPG and measured this: On a + * system with a limit of 4096 files and only 8 files open with the + * highest number being 10, we speedup close_all_fds from 125ms to + * 0.4ms including the readdir. + * + * Another option would be to close the file descriptors as returned + * from reading that directory - however then we need to snapshot + * that list before starting to close them. */ +#ifdef __linux__ + { + DIR *dir = NULL; + struct dirent *dir_entry; + const char *s; + int x; + + dir = opendir ("/proc/self/fd"); + if (dir) + { + while ((dir_entry = readdir (dir))) + { + s = dir_entry->d_name; + if ( *s < '0' || *s > '9') + continue; + x = atoi (s); + if (x > max_fds) + max_fds = x; + } + closedir (dir); + } + if (max_fds != -1) + return max_fds + 1; + } +#endif /* __linux__ */ + # ifdef RLIMIT_NOFILE if (!getrlimit (RLIMIT_NOFILE, &rl)) max_fds = rl.rlim_max; |