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