| Josh Gao | 9727192 | 2019-11-06 13:15:00 -0800 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2020 The Android Open Source Project | 
|  | 3 | * | 
|  | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | * you may not use this file except in compliance with the License. | 
|  | 6 | * You may obtain a copy of the License at | 
|  | 7 | * | 
|  | 8 | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | * | 
|  | 10 | * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | * See the License for the specific language governing permissions and | 
|  | 14 | * limitations under the License. | 
|  | 15 | */ | 
|  | 16 |  | 
|  | 17 | #include <gtest/gtest.h> | 
|  | 18 |  | 
|  | 19 | #include <dirent.h> | 
|  | 20 | #include <err.h> | 
|  | 21 | #include <errno.h> | 
|  | 22 | #include <fcntl.h> | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 23 | #include <netinet/in.h> | 
| Josh Gao | 9727192 | 2019-11-06 13:15:00 -0800 | [diff] [blame] | 24 | #include <stdlib.h> | 
| Josh Gao | a38331d | 2020-04-29 17:06:14 -0700 | [diff] [blame] | 25 | #include <sys/epoll.h> | 
| Josh Gao | 7de4124 | 2020-04-29 17:08:46 -0700 | [diff] [blame] | 26 | #include <sys/eventfd.h> | 
| Josh Gao | 9727192 | 2019-11-06 13:15:00 -0800 | [diff] [blame] | 27 | #include <sys/types.h> | 
|  | 28 | #include <unistd.h> | 
|  | 29 |  | 
|  | 30 | #if defined(__BIONIC__) | 
| Josh Gao | 3de1915 | 2021-02-22 18:09:48 -0800 | [diff] [blame] | 31 | #include <sys/pidfd.h> | 
|  | 32 |  | 
| Josh Gao | 7596250 | 2020-01-28 13:24:33 -0800 | [diff] [blame] | 33 | #include "platform/bionic/fdtrack.h" | 
| Josh Gao | 9413ae7 | 2020-04-30 16:03:44 -0700 | [diff] [blame] | 34 | #include "platform/bionic/reserved_signals.h" | 
| Josh Gao | 9727192 | 2019-11-06 13:15:00 -0800 | [diff] [blame] | 35 | #endif | 
|  | 36 |  | 
|  | 37 | #include <vector> | 
|  | 38 |  | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 39 | #include <android-base/cmsg.h> | 
| Josh Gao | 9413ae7 | 2020-04-30 16:03:44 -0700 | [diff] [blame] | 40 | #include <android-base/logging.h> | 
| Josh Gao | 9727192 | 2019-11-06 13:15:00 -0800 | [diff] [blame] | 41 | #include <android-base/unique_fd.h> | 
|  | 42 |  | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 43 | using android::base::ReceiveFileDescriptors; | 
|  | 44 | using android::base::SendFileDescriptors; | 
|  | 45 | using android::base::unique_fd; | 
|  | 46 |  | 
| Josh Gao | 9727192 | 2019-11-06 13:15:00 -0800 | [diff] [blame] | 47 | #if defined(__BIONIC__) | 
| Josh Gao | 9413ae7 | 2020-04-30 16:03:44 -0700 | [diff] [blame] | 48 | void DumpEvent(std::vector<android_fdtrack_event>* events, size_t index) { | 
|  | 49 | auto& event = (*events)[index]; | 
|  | 50 | if (event.type == ANDROID_FDTRACK_EVENT_TYPE_CREATE) { | 
|  | 51 | fprintf(stderr, "  event %zu: fd %d created by %s\n", index, event.fd, | 
|  | 52 | event.data.create.function_name); | 
|  | 53 | } else if (event.type == ANDROID_FDTRACK_EVENT_TYPE_CLOSE) { | 
|  | 54 | fprintf(stderr, "  event %zu: fd %d closed\n", index, event.fd); | 
|  | 55 | } else { | 
|  | 56 | errx(1, "unexpected fdtrack event type: %d", event.type); | 
|  | 57 | } | 
|  | 58 | } | 
|  | 59 |  | 
| Josh Gao | dcc97c0 | 2020-12-09 14:01:13 -0800 | [diff] [blame] | 60 | std::vector<android_fdtrack_event> FdtrackRun(void (*func)(), bool reenable = true) { | 
| Josh Gao | 9727192 | 2019-11-06 13:15:00 -0800 | [diff] [blame] | 61 | // Each bionic test is run in separate process, so we can safely use a static here. | 
| Josh Gao | dcc97c0 | 2020-12-09 14:01:13 -0800 | [diff] [blame] | 62 | // However, since they're all forked, we need to reenable fdtrack. | 
|  | 63 | if (reenable) { | 
|  | 64 | android_fdtrack_set_globally_enabled(true); | 
|  | 65 | } | 
|  | 66 |  | 
| Josh Gao | 9727192 | 2019-11-06 13:15:00 -0800 | [diff] [blame] | 67 | static std::vector<android_fdtrack_event> events; | 
|  | 68 | events.clear(); | 
|  | 69 |  | 
|  | 70 | android_fdtrack_hook_t previous = nullptr; | 
| Josh Gao | 3de1915 | 2021-02-22 18:09:48 -0800 | [diff] [blame] | 71 | android_fdtrack_hook_t hook = [](android_fdtrack_event* event) { events.push_back(*event); }; | 
| Josh Gao | 9727192 | 2019-11-06 13:15:00 -0800 | [diff] [blame] | 72 |  | 
|  | 73 | if (!android_fdtrack_compare_exchange_hook(&previous, hook)) { | 
|  | 74 | errx(1, "failed to exchange hook: previous hook was %p", previous); | 
|  | 75 | } | 
|  | 76 |  | 
|  | 77 | if (previous) { | 
|  | 78 | errx(1, "hook was already registered?"); | 
|  | 79 | abort(); | 
|  | 80 | } | 
|  | 81 |  | 
|  | 82 | func(); | 
|  | 83 |  | 
|  | 84 | if (!android_fdtrack_compare_exchange_hook(&hook, nullptr)) { | 
|  | 85 | errx(1, "failed to reset hook"); | 
|  | 86 | } | 
|  | 87 |  | 
| Josh Gao | 9413ae7 | 2020-04-30 16:03:44 -0700 | [diff] [blame] | 88 | // Filter out temporary fds created and closed as a result of the call. | 
|  | 89 | // (e.g. accept creating a socket to tell netd about the newly accepted socket) | 
|  | 90 | size_t i = 0; | 
|  | 91 | while (i + 1 < events.size()) { | 
|  | 92 | auto& event = events[i]; | 
|  | 93 | if (event.type == ANDROID_FDTRACK_EVENT_TYPE_CREATE) { | 
|  | 94 | for (size_t j = i + 1; j < events.size(); ++j) { | 
|  | 95 | if (event.fd == events[j].fd) { | 
|  | 96 | if (events[j].type == ANDROID_FDTRACK_EVENT_TYPE_CREATE) { | 
|  | 97 | fprintf(stderr, "error: multiple create events for the same fd:\n"); | 
|  | 98 | DumpEvent(&events, i); | 
|  | 99 | DumpEvent(&events, j); | 
|  | 100 | exit(1); | 
|  | 101 | } | 
|  | 102 |  | 
|  | 103 | events.erase(events.begin() + j); | 
|  | 104 | events.erase(events.begin() + i); | 
|  | 105 | continue; | 
|  | 106 | } | 
|  | 107 | } | 
|  | 108 | } | 
|  | 109 | ++i; | 
|  | 110 | } | 
|  | 111 |  | 
| Josh Gao | 9727192 | 2019-11-06 13:15:00 -0800 | [diff] [blame] | 112 | return std::move(events); | 
|  | 113 | } | 
| Josh Gao | 9727192 | 2019-11-06 13:15:00 -0800 | [diff] [blame] | 114 |  | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 115 | const char* FdtrackEventTypeToName(android_fdtrack_event_type event_type) { | 
|  | 116 | switch (event_type) { | 
|  | 117 | case ANDROID_FDTRACK_EVENT_TYPE_CREATE: | 
|  | 118 | return "created"; | 
|  | 119 | case ANDROID_FDTRACK_EVENT_TYPE_CLOSE: | 
|  | 120 | return "closed"; | 
|  | 121 | } | 
| Josh Gao | 9727192 | 2019-11-06 13:15:00 -0800 | [diff] [blame] | 122 | } | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 123 | #endif | 
| Josh Gao | 9727192 | 2019-11-06 13:15:00 -0800 | [diff] [blame] | 124 |  | 
|  | 125 | TEST(fdtrack, close) { | 
|  | 126 | #if defined(__BIONIC__) | 
|  | 127 | static int fd = open("/dev/null", O_WRONLY | O_CLOEXEC); | 
|  | 128 | ASSERT_NE(-1, fd); | 
|  | 129 |  | 
|  | 130 | auto events = FdtrackRun([]() { close(fd); }); | 
|  | 131 | ASSERT_EQ(1U, events.size()); | 
|  | 132 | ASSERT_EQ(fd, events[0].fd); | 
|  | 133 | ASSERT_EQ(ANDROID_FDTRACK_EVENT_TYPE_CLOSE, events[0].type); | 
|  | 134 | #endif | 
|  | 135 | } | 
|  | 136 |  | 
| Josh Gao | dcc97c0 | 2020-12-09 14:01:13 -0800 | [diff] [blame] | 137 | TEST(fdtrack, fork) { | 
|  | 138 | #if defined(__BIONIC__) | 
|  | 139 | ASSERT_EXIT( | 
|  | 140 | []() { | 
|  | 141 | static int fd = open("/dev/null", O_WRONLY | O_CLOEXEC); | 
|  | 142 | ASSERT_NE(-1, fd); | 
|  | 143 |  | 
|  | 144 | auto events = FdtrackRun([]() { close(fd); }, false); | 
|  | 145 | ASSERT_EQ(0U, events.size()); | 
|  | 146 | exit(0); | 
|  | 147 | }(), | 
|  | 148 | testing::ExitedWithCode(0), ""); | 
|  | 149 | #endif | 
|  | 150 | } | 
|  | 151 |  | 
| Josh Gao | 9727192 | 2019-11-06 13:15:00 -0800 | [diff] [blame] | 152 | TEST(fdtrack, enable_disable) { | 
|  | 153 | #if defined(__BIONIC__) | 
|  | 154 | static int fd1 = -1; | 
|  | 155 | static int fd2 = -1; | 
|  | 156 | static int fd3 = -1; | 
|  | 157 |  | 
|  | 158 | auto events = FdtrackRun([]() { | 
|  | 159 | if (!android_fdtrack_get_enabled()) { | 
|  | 160 | errx(1, "fdtrack is disabled"); | 
|  | 161 | } | 
|  | 162 | fd1 = open("/dev/null", O_WRONLY | O_CLOEXEC); | 
|  | 163 | android_fdtrack_set_enabled(false); | 
|  | 164 | fd2 = open("/dev/null", O_WRONLY | O_CLOEXEC); | 
|  | 165 | android_fdtrack_set_enabled(true); | 
|  | 166 | fd3 = open("/dev/null", O_WRONLY | O_CLOEXEC); | 
|  | 167 | }); | 
|  | 168 |  | 
|  | 169 | if (fd1 == -1 || fd2 == -1 || fd3 == -1) { | 
|  | 170 | errx(1, "failed to open /dev/null"); | 
|  | 171 | } | 
|  | 172 |  | 
|  | 173 | ASSERT_EQ(2U, events.size()); | 
|  | 174 |  | 
|  | 175 | ASSERT_EQ(fd1, events[0].fd); | 
|  | 176 | ASSERT_EQ(ANDROID_FDTRACK_EVENT_TYPE_CREATE, events[0].type); | 
|  | 177 | ASSERT_STREQ("open", events[0].data.create.function_name); | 
|  | 178 |  | 
|  | 179 | ASSERT_EQ(fd3, events[1].fd); | 
|  | 180 | ASSERT_EQ(ANDROID_FDTRACK_EVENT_TYPE_CREATE, events[1].type); | 
|  | 181 | ASSERT_STREQ("open", events[1].data.create.function_name); | 
|  | 182 | #endif | 
|  | 183 | } | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 184 |  | 
|  | 185 | struct require_semicolon; | 
|  | 186 |  | 
|  | 187 | #if defined(__BIONIC__) | 
| Josh Gao | 1fad528 | 2020-04-29 17:00:13 -0700 | [diff] [blame] | 188 | void SetFdResult(std::vector<int>* output, int fd) { | 
|  | 189 | output->push_back(fd); | 
|  | 190 | } | 
|  | 191 |  | 
|  | 192 | void SetFdResult(std::vector<int>* output, std::vector<int> fds) { | 
|  | 193 | *output = fds; | 
|  | 194 | } | 
|  | 195 |  | 
|  | 196 | #define FDTRACK_TEST_NAME(test_name, fdtrack_name, expression)                                   \ | 
|  | 197 | TEST(fdtrack, test_name) {                                                                     \ | 
|  | 198 | static std::vector<int> expected_fds;                                                        \ | 
|  | 199 | auto events = FdtrackRun([]() { SetFdResult(&expected_fds, expression); });                  \ | 
|  | 200 | for (auto& fd : expected_fds) {                                                              \ | 
| Josh Gao | 3de1915 | 2021-02-22 18:09:48 -0800 | [diff] [blame] | 201 | ASSERT_NE(-1, fd) << strerror(errno);                                                      \ | 
| Josh Gao | 1fad528 | 2020-04-29 17:00:13 -0700 | [diff] [blame] | 202 | }                                                                                            \ | 
|  | 203 | if (events.size() != expected_fds.size()) {                                                  \ | 
|  | 204 | fprintf(stderr, "too many events received: expected %zu, got %zu:\n", expected_fds.size(), \ | 
|  | 205 | events.size());                                                                    \ | 
|  | 206 | for (size_t i = 0; i < events.size(); ++i) {                                               \ | 
| Josh Gao | 9413ae7 | 2020-04-30 16:03:44 -0700 | [diff] [blame] | 207 | DumpEvent(&events, i);                                                                   \ | 
| Josh Gao | 1fad528 | 2020-04-29 17:00:13 -0700 | [diff] [blame] | 208 | }                                                                                          \ | 
|  | 209 | FAIL();                                                                                    \ | 
|  | 210 | return;                                                                                    \ | 
|  | 211 | }                                                                                            \ | 
|  | 212 | for (auto& event : events) {                                                                 \ | 
|  | 213 | ASSERT_NE(expected_fds.end(),                                                              \ | 
|  | 214 | std::find(expected_fds.begin(), expected_fds.end(), events[0].fd));              \ | 
|  | 215 | ASSERT_EQ(ANDROID_FDTRACK_EVENT_TYPE_CREATE, event.type);                                  \ | 
|  | 216 | ASSERT_STREQ(fdtrack_name, event.data.create.function_name);                               \ | 
|  | 217 | }                                                                                            \ | 
|  | 218 | }                                                                                              \ | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 219 | struct require_semicolon | 
|  | 220 | #else | 
|  | 221 | #define FDTRACK_TEST_NAME(name, fdtrack_name, expression) \ | 
|  | 222 | TEST(fdtrack, name) {}                                  \ | 
|  | 223 | struct require_semicolon | 
|  | 224 | #endif | 
|  | 225 |  | 
|  | 226 | #define FDTRACK_TEST(name, expression) FDTRACK_TEST_NAME(name, #name, expression) | 
|  | 227 |  | 
|  | 228 | // clang-format misformats statement expressions pretty badly here: | 
|  | 229 | // clang-format off | 
|  | 230 | FDTRACK_TEST(open, open("/dev/null", O_WRONLY | O_CLOEXEC)); | 
|  | 231 | FDTRACK_TEST(openat, openat(AT_EMPTY_PATH, "/dev/null", O_WRONLY | O_CLOEXEC)); | 
|  | 232 | FDTRACK_TEST(socket, socket(AF_UNIX, SOCK_STREAM, 0)); | 
|  | 233 |  | 
| Josh Gao | 3de1915 | 2021-02-22 18:09:48 -0800 | [diff] [blame] | 234 | FDTRACK_TEST(pidfd_open, ({ | 
|  | 235 | int rc = pidfd_open(getpid(), 0); | 
|  | 236 | if (rc == -1) { | 
|  | 237 | ASSERT_EQ(ENOSYS, errno); | 
|  | 238 | GTEST_SKIP() << "pidfd_open not available"; | 
|  | 239 | } | 
|  | 240 | rc; | 
|  | 241 | })); | 
|  | 242 |  | 
|  | 243 | FDTRACK_TEST(pidfd_getfd, ({ | 
|  | 244 | android_fdtrack_set_enabled(false); | 
|  | 245 | int pidfd_self = pidfd_open(getpid(), 0); | 
|  | 246 | if (pidfd_self == -1) { | 
|  | 247 | ASSERT_EQ(ENOSYS, errno); | 
|  | 248 | GTEST_SKIP() << "pidfd_open not available"; | 
|  | 249 | } | 
|  | 250 | android_fdtrack_set_enabled(true); | 
|  | 251 |  | 
|  | 252 | int rc = pidfd_getfd(pidfd_self, STDIN_FILENO, 0); | 
|  | 253 | if (rc == -1) { | 
|  | 254 | ASSERT_EQ(ENOSYS, errno); | 
|  | 255 | GTEST_SKIP() << "pidfd_getfd not available"; | 
|  | 256 | } | 
|  | 257 |  | 
|  | 258 | android_fdtrack_set_enabled(false); | 
|  | 259 | close(pidfd_self); | 
|  | 260 | android_fdtrack_set_enabled(true); | 
|  | 261 |  | 
|  | 262 | rc; | 
|  | 263 | })); | 
|  | 264 |  | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 265 | FDTRACK_TEST(dup, dup(STDOUT_FILENO)); | 
|  | 266 | FDTRACK_TEST(dup2, dup2(STDOUT_FILENO, STDERR_FILENO)); | 
|  | 267 | FDTRACK_TEST(dup3, dup3(STDOUT_FILENO, STDERR_FILENO, 0)); | 
|  | 268 | FDTRACK_TEST_NAME(fcntl_F_DUPFD, "F_DUPFD", fcntl(STDOUT_FILENO, F_DUPFD, 0)); | 
|  | 269 | FDTRACK_TEST_NAME(fcntl_F_DUPFD_CLOEXEC, "F_DUPFD_CLOEXEC", fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0)); | 
|  | 270 |  | 
| Josh Gao | 1fad528 | 2020-04-29 17:00:13 -0700 | [diff] [blame] | 271 | FDTRACK_TEST(pipe, ({ | 
|  | 272 | std::vector<int> fds = { -1, -1}; | 
|  | 273 | if (pipe(fds.data()) != 0) { | 
|  | 274 | err(1, "pipe failed"); | 
|  | 275 | } | 
|  | 276 | fds; | 
|  | 277 | })); | 
|  | 278 |  | 
|  | 279 | FDTRACK_TEST(pipe2, ({ | 
|  | 280 | std::vector<int> fds = { -1, -1}; | 
|  | 281 | if (pipe2(fds.data(), O_CLOEXEC) != 0) { | 
|  | 282 | err(1, "pipe failed"); | 
|  | 283 | } | 
|  | 284 | fds; | 
|  | 285 | })); | 
|  | 286 |  | 
| Josh Gao | b107eab | 2020-04-29 17:17:56 -0700 | [diff] [blame] | 287 | FDTRACK_TEST(socketpair, ({ | 
|  | 288 | std::vector<int> fds = { -1, -1}; | 
|  | 289 | if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds.data()) != 0) { | 
|  | 290 | err(1, "socketpair failed"); | 
|  | 291 | } | 
|  | 292 | fds; | 
|  | 293 | })); | 
|  | 294 |  | 
| Josh Gao | a38331d | 2020-04-29 17:06:14 -0700 | [diff] [blame] | 295 | FDTRACK_TEST(epoll_create, epoll_create(1)); | 
|  | 296 | FDTRACK_TEST(epoll_create1, epoll_create1(0)); | 
|  | 297 |  | 
| Josh Gao | 7de4124 | 2020-04-29 17:08:46 -0700 | [diff] [blame] | 298 | FDTRACK_TEST(eventfd, eventfd(0, 0)); | 
|  | 299 |  | 
| Josh Gao | 9413ae7 | 2020-04-30 16:03:44 -0700 | [diff] [blame] | 300 | #if defined(__BIONIC__) | 
|  | 301 | static int CreateListener() { | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 302 | android_fdtrack_set_enabled(false); | 
|  | 303 | int listener = socket(AF_INET, SOCK_STREAM, 0); | 
| Josh Gao | 9413ae7 | 2020-04-30 16:03:44 -0700 | [diff] [blame] | 304 | CHECK_NE(-1, listener); | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 305 |  | 
|  | 306 | sockaddr_in addr = { | 
|  | 307 | .sin_family = AF_INET, | 
|  | 308 | .sin_port = 0, | 
|  | 309 | .sin_addr = {htonl(INADDR_LOOPBACK)}, | 
|  | 310 | }; | 
|  | 311 | socklen_t addrlen = sizeof(addr); | 
|  | 312 |  | 
| Josh Gao | 9413ae7 | 2020-04-30 16:03:44 -0700 | [diff] [blame] | 313 | CHECK_NE(-1, bind(listener, reinterpret_cast<sockaddr*>(&addr), addrlen)) << strerror(errno); | 
|  | 314 | CHECK_NE(-1, getsockname(listener, reinterpret_cast<sockaddr*>(&addr), &addrlen)); | 
|  | 315 | CHECK_EQ(static_cast<size_t>(addrlen), sizeof(addr)); | 
|  | 316 | CHECK_NE(-1, listen(listener, 1)); | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 317 |  | 
|  | 318 | int connector = socket(AF_INET, SOCK_STREAM, 0); | 
| Josh Gao | 9413ae7 | 2020-04-30 16:03:44 -0700 | [diff] [blame] | 319 | CHECK_NE(-1, connector); | 
|  | 320 | CHECK_NE(-1, connect(connector, reinterpret_cast<sockaddr*>(&addr), addrlen)); | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 321 | android_fdtrack_set_enabled(true); | 
| Josh Gao | 9413ae7 | 2020-04-30 16:03:44 -0700 | [diff] [blame] | 322 |  | 
|  | 323 | return listener; | 
|  | 324 | } | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 325 | #endif | 
|  | 326 |  | 
| Josh Gao | 9413ae7 | 2020-04-30 16:03:44 -0700 | [diff] [blame] | 327 | FDTRACK_TEST_NAME(accept, "accept4", accept(CreateListener(), nullptr, nullptr)); | 
|  | 328 | FDTRACK_TEST(accept4, accept4(CreateListener(), nullptr, nullptr, 0)); | 
|  | 329 |  | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 330 | FDTRACK_TEST(recvmsg, ({ | 
|  | 331 | android_fdtrack_set_enabled(false); | 
|  | 332 | int sockets[2]; | 
|  | 333 | ASSERT_NE(-1, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)); | 
|  | 334 | ASSERT_EQ(3, SendFileDescriptors(sockets[0], "foo", 3, STDIN_FILENO)); | 
|  | 335 | android_fdtrack_set_enabled(true); | 
|  | 336 |  | 
|  | 337 | char buf[4]; | 
|  | 338 | unique_fd received_fd; | 
|  | 339 | ASSERT_EQ(3, ReceiveFileDescriptors(sockets[1], buf, sizeof(buf), &received_fd)); | 
|  | 340 | received_fd.release(); | 
|  | 341 | })); | 
| Josh Gao | 4129113 | 2020-05-07 19:43:38 -0700 | [diff] [blame] | 342 |  | 
|  | 343 | FDTRACK_TEST_NAME(vfork, "open", ({ | 
|  | 344 | int fd = open("/dev/null", O_RDONLY); | 
|  | 345 |  | 
|  | 346 | pid_t rc = vfork(); | 
|  | 347 | ASSERT_NE(-1, rc); | 
|  | 348 |  | 
|  | 349 | if (rc == 0) { | 
|  | 350 | close(fd); | 
|  | 351 | _exit(0); | 
|  | 352 | } | 
|  | 353 |  | 
|  | 354 | int status; | 
|  | 355 | pid_t wait_result = waitpid(rc, &status, 0); | 
|  | 356 | ASSERT_EQ(wait_result, rc); | 
|  | 357 | ASSERT_TRUE(WIFEXITED(status)); | 
|  | 358 | ASSERT_EQ(0, WEXITSTATUS(status)); | 
|  | 359 |  | 
|  | 360 | fd; | 
|  | 361 | })); | 
| Josh Gao | 9d51240 | 2020-04-29 16:34:37 -0700 | [diff] [blame] | 362 | // clang-format on |