aboutsummaryrefslogtreecommitdiffstats
path: root/common/exechelp-posix.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2016-05-27 20:02:54 +0000
committerWerner Koch <[email protected]>2016-05-27 20:02:54 +0000
commit512c56af43027149e8beacf259746b8d7bf9b1a2 (patch)
tree7e8e2705c5946fbf9dac8495eae816620ec7d193 /common/exechelp-posix.c
parenttools: Improve debug output of rfc822parse. (diff)
downloadgnupg-512c56af43027149e8beacf259746b8d7bf9b1a2.tar.gz
gnupg-512c56af43027149e8beacf259746b8d7bf9b1a2.zip
common: Speedup closing fds before an exec.
* common/exechelp-posix.c [__linux__]: Include dirent.h. (get_max_fds) [__linux__]: Return the actual used highest fd. -- Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'common/exechelp-posix.c')
-rw-r--r--common/exechelp-posix.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/common/exechelp-posix.c b/common/exechelp-posix.c
index 87c6e5509..81831eeb1 100644
--- a/common/exechelp-posix.c
+++ b/common/exechelp-posix.c
@@ -67,6 +67,11 @@
# include <sys/stat.h>
#endif
+#if __linux__
+# include <sys/types.h>
+# include <dirent.h>
+#endif /*__linux__ */
+
#include "util.h"
#include "i18n.h"
#include "sysutils.h"
@@ -97,6 +102,45 @@ 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 fast than
+ * for example doing 4096 close calls where almost all of them will
+ * fail. 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 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__
+ {
+ char dirname[50];
+ DIR *dir = NULL;
+ struct dirent *dir_entry;
+ const char *s;
+ int x;
+
+ snprintf (dirname, sizeof dirname, "/proc/%u/fd", (unsigned int)getpid ());
+ dir = opendir (dirname);
+ 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;