From 8a5bf2ad16c416c389147ca59c56545e038470e1 Mon Sep 17 00:00:00 2001 From: John Eckersberg Date: Fri, 11 Oct 2019 13:06:20 -0400 Subject: [PATCH] erl_child_setup: reduce number of calls to close() On systems without closefrom(), such as Linux, iterating over all possible file descriptors and calling close() for each is inefficient. This is markedly so when the maximum number of file descriptors has been tuned to a large number. Instead, walk the open descriptors under /dev/fd and close only those which are open. --- erts/emulator/sys/unix/erl_child_setup.c | 25 +++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/erts/emulator/sys/unix/erl_child_setup.c b/erts/emulator/sys/unix/erl_child_setup.c index 129861ebd5..7ddd753136 100644 --- a/erts/emulator/sys/unix/erl_child_setup.c +++ b/erts/emulator/sys/unix/erl_child_setup.c @@ -411,6 +411,7 @@ main(int argc, char *argv[]) int uds_fd = 3, max_fd = 3; #ifndef HAVE_CLOSEFROM int i; + DIR *dir; #endif struct sigaction sa; @@ -426,11 +427,29 @@ main(int argc, char *argv[]) #if defined(HAVE_CLOSEFROM) closefrom(4); #else - for (i = 4; i < max_files; i++) + dir = opendir("/dev/fd"); + if (dir == NULL) { /* /dev/fd not available */ + for (i = 4; i < max_files; i++) #if defined(__ANDROID__) - if (i != system_properties_fd()) + if (i != system_properties_fd()) #endif - (void) close(i); + (void) close(i); + } else { + /* Iterate over fds obtained from /dev/fd */ + struct dirent *entry; + int dir_fd = dirfd(dir); + + while ((entry = readdir(dir)) != NULL) { + i = atoi(entry->d_name); +#if defined(__ANDROID__) + if (i != system_properties_fd()) +#endif + if (i >= 4 && i != dir_fd) + (void) close(i); + } + + closedir(dir); + } #endif if (pipe(sigchld_pipe) < 0) { -- 2.23.0