Skip to content

Commit d378a9f

Browse files
authored
Improve js_os_exec (#295)
- use $(shell) make command to test if closefrom() is available - use closefrom() if available in js_os_exec() - limit the fallback loop to 1024 handles to avoid costly loop on linux alpine. PR inspired by @nicolas-duteil-nova
1 parent 97be5a3 commit d378a9f

File tree

3 files changed

+33
-4
lines changed

3 files changed

+33
-4
lines changed

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ endif
143143
ifdef CONFIG_WIN32
144144
DEFINES+=-D__USE_MINGW_ANSI_STDIO # for standard snprintf behavior
145145
endif
146+
ifndef CONFIG_WIN32
147+
ifeq ($(shell $(CC) -o /dev/null compat/test-closefrom.c 2>/dev/null && echo 1),1)
148+
DEFINES+=-DHAVE_CLOSEFROM
149+
endif
150+
endif
146151

147152
CFLAGS+=$(DEFINES)
148153
CFLAGS_DEBUG=$(CFLAGS) -O0

compat/test-closefrom.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <unistd.h>
2+
3+
int main(void) {
4+
closefrom(3);
5+
return 0;
6+
}

quickjs-libc.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3015,7 +3015,6 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
30153015
}
30163016
if (pid == 0) {
30173017
/* child */
3018-
int fd_max = sysconf(_SC_OPEN_MAX);
30193018

30203019
/* remap the stdin/stdout/stderr handles if necessary */
30213020
for(i = 0; i < 3; i++) {
@@ -3024,9 +3023,28 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
30243023
_exit(127);
30253024
}
30263025
}
3027-
3028-
for(i = 3; i < fd_max; i++)
3029-
close(i);
3026+
#if defined(HAVE_CLOSEFROM)
3027+
/* closefrom() is available on many recent unix systems:
3028+
Linux with glibc 2.34+, Solaris 9+, FreeBSD 7.3+,
3029+
NetBSD 3.0+, OpenBSD 3.5+.
3030+
Linux with the musl libc and macOS don't have it.
3031+
*/
3032+
3033+
closefrom(3);
3034+
#else
3035+
{
3036+
/* Close the file handles manually, limit to 1024 to avoid
3037+
costly loop on linux Alpine where sysconf(_SC_OPEN_MAX)
3038+
returns a huge value 1048576.
3039+
Patch inspired by nicolas-duteil-nova. See also:
3040+
https://stackoverflow.com/questions/73229353/
3041+
https://stackoverflow.com/questions/899038/#918469
3042+
*/
3043+
int fd_max = min_int(sysconf(_SC_OPEN_MAX), 1024);
3044+
for(i = 3; i < fd_max; i++)
3045+
close(i);
3046+
}
3047+
#endif
30303048
if (cwd) {
30313049
if (chdir(cwd) < 0)
30323050
_exit(127);

0 commit comments

Comments
 (0)