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

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