From 5340a772ad3958d06e41649ae1f4e0c678259848 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 23 Feb 2022 18:21:58 -0500 Subject: [PATCH] test: verify the number of fds on start Helps ensure that we do not accidentally leak an fd unintentionally during uv_spawn. --- test/run-tests.c | 10 +++++++ test/runner-unix.c | 66 +++++++++++++++++++++++++++++++++++++++++++++- test/task.h | 3 +++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/test/run-tests.c b/test/run-tests.c index 86b03599..57c3de5e 100644 --- a/test/run-tests.c +++ b/test/run-tests.c @@ -75,6 +75,16 @@ int main(int argc, char **argv) { platform_init(argc, argv); argv = uv_setup_args(argc, argv); + if ((argc == 2 || argc == 4) && strcmp(argv[1], "spawn_helper5") == 0) { + uv__check_nfd(4); + } else if ((argc == 2 || argc == 4) && strcmp(argv[1], "spawn_tcp_server_helper") == 0) { + uv__check_nfd(4); + } else if ((argc == 2 || argc == 4) && strcmp(argv[1], "spawn_helper8") == 0) { + /* skip */ + } else { + uv__check_nfd(3); + } + switch (argc) { case 1: return run_tests(0); case 2: return maybe_run_test(argc, argv); diff --git a/test/runner-unix.c b/test/runner-unix.c index a13648bc..2cc50253 100644 --- a/test/runner-unix.c +++ b/test/runner-unix.c @@ -21,6 +21,7 @@ #include "runner-unix.h" #include "runner.h" +#include "task.h" #include #include /* uintptr_t */ @@ -35,6 +36,7 @@ #include #include #include +#include #include #include @@ -51,6 +53,67 @@ static void closefd(int fd) { } +static int uv__cloexec(int fd, int set) { + int flags; + int r; + + do + r = fcntl(fd, F_GETFD); + while (r == -1 && errno == EINTR); + + if (r == -1) + return errno; + + /* Bail out now if already set/clear. */ + if (!!(r & FD_CLOEXEC) == !!set) + return 0; + + if (set) + flags = r | FD_CLOEXEC; + else + flags = r & ~FD_CLOEXEC; + + do + r = fcntl(fd, F_SETFD, flags); + while (r == -1 && errno == EINTR); + + if (r) + return errno; + + return 0; +} + + +void uv__check_nfd(int nfd) { + const char *arg; + int fd; + int test_runner_fd = -1; + int mode; + + arg = getenv("UV_TEST_RUNNER_FD"); + if (arg) { + test_runner_fd = atoi(arg); + ASSERT_GE(test_runner_fd, nfd); + } + + for (fd = 0; fd < 2048; fd++) { + do + mode = fcntl(fd, F_GETFL); + while (mode == -1 && errno == EINTR); + + if (fd < nfd || fd == test_runner_fd) { + ASSERT_GE(mode, 0); + } else if (mode != -1 || errno != EBADF) { + /* Try to print some helpful debugging output before the abort. */ + char args[32]; + snprintf(args, sizeof(args), "lsof -p %u,%u", getpid(), getppid()); + system(args); + ASSERT_EQ(fd, -1); + } + } +} + + void notify_parent_process(void) { char* arg; int fd; @@ -109,11 +172,12 @@ int process_start(char* name, char* part, process_info_t* p, int is_helper) { args[n++] = NULL; stdout_file = tmpfile(); - stdout_fd = fileno(stdout_file); if (!stdout_file) { perror("tmpfile"); return -1; } + stdout_fd = fileno(stdout_file); + uv__cloexec(stdout_fd, 1); if (is_helper) { if (pipe(pipefd)) { diff --git a/test/task.h b/test/task.h index 925f1b1c..cae27b28 100644 --- a/test/task.h +++ b/test/task.h @@ -323,10 +323,13 @@ extern int snprintf(char*, size_t, const char*, ...); #if defined(_WIN32) #define notify_parent_process() ((void) 0) +#define uv__check_nfd(nfd) ((void) nfd) #else extern void notify_parent_process(void); +extern void uv__check_nfd(int nfd); #endif + /* Fully close a loop */ static void close_walk_cb(uv_handle_t* handle, void* arg) { if (!uv_is_closing(handle))