mirror of
https://github.com/apple/container.git
synced 2026-09-11 10:15:38 +00:00
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.
This commit is contained in:
@@ -14,8 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
@@ -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
|
||||
@@ -17,6 +17,8 @@
|
||||
#ifndef exec_command_h
|
||||
#define exec_command_h
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user