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

John Eckersberg dd8ae3
From 8a5bf2ad16c416c389147ca59c56545e038470e1 Mon Sep 17 00:00:00 2001
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
 erts/emulator/sys/unix/erl_child_setup.c | 25 +++++++++++++++++++++---
John Eckersberg dd8ae3
 1 file changed, 22 insertions(+), 3 deletions(-)
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) {
John Eckersberg dd8ae3
-- 
John Eckersberg dd8ae3
2.23.0
John Eckersberg dd8ae3