diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT index ab309e629..cf7d58b5e 100644 --- a/libc/SYSCALLS.TXT +++ b/libc/SYSCALLS.TXT @@ -126,7 +126,7 @@ int __fcntl64:fcntl64(int, int, void*) lp32 int __fcntl:fcntl(int, int, void*) lp64 int flock(int, int) all int __fchmod:fchmod(int, mode_t) all -int pipe2(int*, int) all +int __pipe2:pipe2(int*, int) all int __dup:dup(int) all int __dup3:dup3(int, int, int) all int fsync(int) all diff --git a/libc/bionic/pipe.cpp b/libc/bionic/pipe.cpp index a81afe8e0..f1976568f 100644 --- a/libc/bionic/pipe.cpp +++ b/libc/bionic/pipe.cpp @@ -28,6 +28,24 @@ #include +#include "private/bionic_fdtrack.h" + +extern "C" int __pipe2(int pipefd[2], int flags); + int pipe(int pipefd[2]) { - return pipe2(pipefd, 0); + int rc = __pipe2(pipefd, 0); + if (rc == 0) { + FDTRACK_CREATE(pipefd[0]); + FDTRACK_CREATE(pipefd[1]); + } + return rc; +} + +int pipe2(int pipefd[2], int flags) { + int rc = __pipe2(pipefd, flags); + if (rc == 0) { + FDTRACK_CREATE(pipefd[0]); + FDTRACK_CREATE(pipefd[1]); + } + return rc; } diff --git a/tests/fdtrack_test.cpp b/tests/fdtrack_test.cpp index 710aa005a..4e6feed38 100644 --- a/tests/fdtrack_test.cpp +++ b/tests/fdtrack_test.cpp @@ -125,32 +125,45 @@ TEST(fdtrack, enable_disable) { struct require_semicolon; #if defined(__BIONIC__) -#define FDTRACK_TEST_NAME(test_name, fdtrack_name, expression) \ - TEST(fdtrack, test_name) { \ - static int fd = -1; \ - auto events = FdtrackRun([]() { fd = expression; }); \ - ASSERT_NE(-1, fd); \ - if (events.size() != 1) { \ - fprintf(stderr, "too many events received: expected 1, got %zu:\n", events.size()); \ - for (size_t i = 0; i < events.size(); ++i) { \ - auto& event = events[i]; \ - if (event.type == ANDROID_FDTRACK_EVENT_TYPE_CREATE) { \ - fprintf(stderr, " event %zu: fd %d created by %s\n", i, event.fd, \ - event.data.create.function_name); \ - } else if (event.type == ANDROID_FDTRACK_EVENT_TYPE_CLOSE) { \ - fprintf(stderr, " event %zu: fd %d closed\n", i, event.fd); \ - } else { \ - errx(1, "unexpected fdtrack event type: %d", event.type); \ - } \ - } \ - FAIL(); \ - return; \ - } \ - ASSERT_EQ(1U, events.size()); \ - ASSERT_EQ(fd, events[0].fd); \ - ASSERT_EQ(ANDROID_FDTRACK_EVENT_TYPE_CREATE, events[0].type); \ - ASSERT_STREQ(fdtrack_name, events[0].data.create.function_name); \ - } \ +void SetFdResult(std::vector* output, int fd) { + output->push_back(fd); +} + +void SetFdResult(std::vector* output, std::vector fds) { + *output = fds; +} + +#define FDTRACK_TEST_NAME(test_name, fdtrack_name, expression) \ + TEST(fdtrack, test_name) { \ + static std::vector expected_fds; \ + auto events = FdtrackRun([]() { SetFdResult(&expected_fds, expression); }); \ + for (auto& fd : expected_fds) { \ + ASSERT_NE(-1, fd); \ + } \ + if (events.size() != expected_fds.size()) { \ + fprintf(stderr, "too many events received: expected %zu, got %zu:\n", expected_fds.size(), \ + events.size()); \ + for (size_t i = 0; i < events.size(); ++i) { \ + auto& event = events[i]; \ + if (event.type == ANDROID_FDTRACK_EVENT_TYPE_CREATE) { \ + fprintf(stderr, " event %zu: fd %d created by %s\n", i, event.fd, \ + event.data.create.function_name); \ + } else if (event.type == ANDROID_FDTRACK_EVENT_TYPE_CLOSE) { \ + fprintf(stderr, " event %zu: fd %d closed\n", i, event.fd); \ + } else { \ + errx(1, "unexpected fdtrack event type: %d", event.type); \ + } \ + } \ + FAIL(); \ + return; \ + } \ + for (auto& event : events) { \ + ASSERT_NE(expected_fds.end(), \ + std::find(expected_fds.begin(), expected_fds.end(), events[0].fd)); \ + ASSERT_EQ(ANDROID_FDTRACK_EVENT_TYPE_CREATE, event.type); \ + ASSERT_STREQ(fdtrack_name, event.data.create.function_name); \ + } \ + } \ struct require_semicolon #else #define FDTRACK_TEST_NAME(name, fdtrack_name, expression) \ @@ -172,6 +185,22 @@ FDTRACK_TEST(dup3, dup3(STDOUT_FILENO, STDERR_FILENO, 0)); FDTRACK_TEST_NAME(fcntl_F_DUPFD, "F_DUPFD", fcntl(STDOUT_FILENO, F_DUPFD, 0)); FDTRACK_TEST_NAME(fcntl_F_DUPFD_CLOEXEC, "F_DUPFD_CLOEXEC", fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0)); +FDTRACK_TEST(pipe, ({ + std::vector fds = { -1, -1}; + if (pipe(fds.data()) != 0) { + err(1, "pipe failed"); + } + fds; +})); + +FDTRACK_TEST(pipe2, ({ + std::vector fds = { -1, -1}; + if (pipe2(fds.data(), O_CLOEXEC) != 0) { + err(1, "pipe failed"); + } + fds; +})); + #if 0 // Why is this generating an extra socket/close event? FDTRACK_TEST(accept, ({