From fcd198e9688a25bfaff8de323ed1bed370efb90f Mon Sep 17 00:00:00 2001 From: Danny Canter Date: Tue, 22 Jul 2025 07:30:10 -0700 Subject: [PATCH] ContainerizationOS: Speed up fd closes (#222) Instead of looping through from minimum fd -> rlimit max, we can close_range(2) or read /proc/self/fd on Linux, and read /dev/fd on macOS. --- Sources/CShim/exec_command.c | 70 ++++++++++++++++++++++++---- Sources/CShim/include/exec_command.h | 3 ++ 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/Sources/CShim/exec_command.c b/Sources/CShim/exec_command.c index 673966e4..f3db6d32 100644 --- a/Sources/CShim/exec_command.c +++ b/Sources/CShim/exec_command.c @@ -14,8 +14,12 @@ * limitations under the License. */ +#if defined(__linux__) || defined(__APPLE__) + #include #include +#include +#include #include #include #include @@ -31,6 +35,60 @@ #include "exec_command.h" +#ifndef SYS_close_range +#define SYS_close_range 436 +#endif + +#ifndef CLOSE_RANGE_CLOEXEC +#define CLOSE_RANGE_CLOEXEC 0x4 +#endif + +static int mark_cloexec(int fd) { + int flags = fcntl(fd, F_GETFD); + + if (flags == -1) return flags; + if (flags & FD_CLOEXEC) return 0; + + return fcntl(fd, F_SETFD, flags | FD_CLOEXEC); +} + +static int cloexec_from(int min_fd) { +#if defined(__linux__) + // First try close_range. + long ret = syscall(SYS_close_range, min_fd, ~0U, CLOSE_RANGE_CLOEXEC); + if (ret == 0) { + return 0; + } + const char* dirpath = "/proc/self/fd"; +#elif defined(__APPLE__) + const char* dirpath = "/dev/fd"; +#endif + DIR *dp = opendir(dirpath); + if (!dp) return -1; + + int dp_fd = dirfd(dp); + struct dirent *de; + + while ((de = readdir(dp))) { + if (de->d_name[0] == '.') continue; + + char *end; + long val = strtol(de->d_name, &end, 10); + if (*end || val < 0 || val > INT_MAX) continue; + + int fd = (int)val; + if (fd < min_fd || fd == dp_fd) continue; + + int ret = mark_cloexec(fd); + if (ret != 0) { + return ret; + } + } + close(dp_fd); + closedir(dp); + return 0; +} + void exec_command_attrs_init(struct exec_command_attrs *attrs) { attrs->setpgid = 0; attrs->pgid = 0; @@ -195,16 +253,10 @@ static void child_handler(const int sync_pipes[2], const char *executable, } } - // Get our current open fd limit and close exec everything outside of our - // child's fd_table. - if (getrlimit(RLIMIT_NOFILE, &limits) < 0) { + // close exec everything outside of our child's fd_table. + if (cloexec_from(file_handle_count) != 0) { goto fail; } - for (i = file_handle_count; i <= limits.rlim_cur; i++) { - if (fcntl(i, F_SETFD, FD_CLOEXEC) == -1 && errno != EBADF) { - goto fail; - } - } // set gid if (attrs.gid != -1) { @@ -312,3 +364,5 @@ fail: } return 0; } + +#endif \ No newline at end of file diff --git a/Sources/CShim/include/exec_command.h b/Sources/CShim/include/exec_command.h index b53a34b3..b0b6d2a0 100644 --- a/Sources/CShim/include/exec_command.h +++ b/Sources/CShim/include/exec_command.h @@ -17,6 +17,8 @@ #ifndef exec_command_h #define exec_command_h +#if defined(__linux__) || defined(__APPLE__) + #include #include @@ -46,4 +48,5 @@ int exec_command(pid_t *result, const char *executable, char *const argv[], const int file_handle_count, const char *working_directory, struct exec_command_attrs *attrs); +#endif /* defined(__linux__) || defined(__APPLE__) */ #endif /* exec_command_h */