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. 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) {