diff --git a/test/run-tests.c b/test/run-tests.c index 17fb0e0c..948d6307 100644 --- a/test/run-tests.c +++ b/test/run-tests.c @@ -76,6 +76,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 81560add..e1802dbd 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 @@ -55,6 +57,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; @@ -113,11 +176,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 e25a9c9a..83a77e05 100644 --- a/test/task.h +++ b/test/task.h @@ -326,10 +326,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))