Skip to content

Commit 81e50f3

Browse files
authored
Use closefrom() to close open file descriptors (#712)
Replace the naive close() loop in js_os_exec with closefrom(). On my system RLIMIT_NOFILE is set to 1 million and the delay from the loop gets noticeable when I spawn many processes. Use dlsym() to look up closefrom() because it's not available everywhere (looking at you, musl.) Fixes: #711
1 parent 010777f commit 81e50f3

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

quickjs-libc.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2997,6 +2997,15 @@ static int my_execvpe(const char *filename, char **argv, char **envp)
29972997
return -1;
29982998
}
29992999

3000+
static js_once_t js_os_exec_once = JS_ONCE_INIT;
3001+
3002+
static void (*js_os_exec_closefrom)(int);
3003+
3004+
static void js_os_exec_once_init(void)
3005+
{
3006+
js_os_exec_closefrom = dlsym(RTLD_DEFAULT, "closefrom");
3007+
}
3008+
30003009
/* exec(args[, options]) -> exitcode */
30013010
static JSValue js_os_exec(JSContext *ctx, JSValue this_val,
30023011
int argc, JSValue *argv)
@@ -3116,15 +3125,17 @@ static JSValue js_os_exec(JSContext *ctx, JSValue this_val,
31163125
}
31173126
}
31183127

3128+
// should happen pre-fork because it calls dlsym()
3129+
// and that's not an async-signal-safe function
3130+
js_once(&js_os_exec_once, js_os_exec_once_init);
3131+
31193132
pid = fork();
31203133
if (pid < 0) {
31213134
JS_ThrowTypeError(ctx, "fork error");
31223135
goto exception;
31233136
}
31243137
if (pid == 0) {
31253138
/* child */
3126-
int fd_max = sysconf(_SC_OPEN_MAX);
3127-
31283139
/* remap the stdin/stdout/stderr handles if necessary */
31293140
for(i = 0; i < 3; i++) {
31303141
if (std_fds[i] != i) {
@@ -3133,8 +3144,14 @@ static JSValue js_os_exec(JSContext *ctx, JSValue this_val,
31333144
}
31343145
}
31353146

3136-
for(i = 3; i < fd_max; i++)
3137-
close(i);
3147+
if (js_os_exec_closefrom) {
3148+
js_os_exec_closefrom(3);
3149+
} else {
3150+
int fd_max = sysconf(_SC_OPEN_MAX);
3151+
for(i = 3; i < fd_max; i++)
3152+
close(i);
3153+
}
3154+
31383155
if (cwd) {
31393156
if (chdir(cwd) < 0)
31403157
_exit(127);

0 commit comments

Comments
 (0)