Blame otp-0010-erl_child_setup-reduce-number-of-calls-to-close.patch

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