1*aca3beaaSApple OSS Distributions #ifdef T_NAMESPACE 2*aca3beaaSApple OSS Distributions #undef T_NAMESPACE 3*aca3beaaSApple OSS Distributions #endif 4*aca3beaaSApple OSS Distributions #include <darwintest.h> 5*aca3beaaSApple OSS Distributions 6*aca3beaaSApple OSS Distributions #include <dispatch/dispatch.h> 7*aca3beaaSApple OSS Distributions #include <fcntl.h> 8*aca3beaaSApple OSS Distributions #include <mach/mach.h> 9*aca3beaaSApple OSS Distributions #include <poll.h> 10*aca3beaaSApple OSS Distributions #include <stdint.h> 11*aca3beaaSApple OSS Distributions #include <unistd.h> 12*aca3beaaSApple OSS Distributions 13*aca3beaaSApple OSS Distributions T_GLOBAL_META(T_META_NAMESPACE("xnu.poll"), 14*aca3beaaSApple OSS Distributions T_META_RUN_CONCURRENTLY(true)); 15*aca3beaaSApple OSS Distributions 16*aca3beaaSApple OSS Distributions #define SLEEP_TIME_SECS 1 17*aca3beaaSApple OSS Distributions #define POLL_TIMEOUT_MS 1800 18*aca3beaaSApple OSS Distributions static_assert(POLL_TIMEOUT_MS > (SLEEP_TIME_SECS * 1000), 19*aca3beaaSApple OSS Distributions "poll timeout should be longer than sleep time"); 20*aca3beaaSApple OSS Distributions 21*aca3beaaSApple OSS Distributions /* 22*aca3beaaSApple OSS Distributions * This matches the behavior of other UNIXes, but is under-specified in POSIX. 23*aca3beaaSApple OSS Distributions * 24*aca3beaaSApple OSS Distributions * See <rdar://problem/28372390>. 25*aca3beaaSApple OSS Distributions */ 26*aca3beaaSApple OSS Distributions T_DECL(sleep_with_no_fds, 27*aca3beaaSApple OSS Distributions "poll() called with no fds provided should act like sleep") 28*aca3beaaSApple OSS Distributions { 29*aca3beaaSApple OSS Distributions uint64_t begin_time, sleep_time, poll_time; 30*aca3beaaSApple OSS Distributions struct pollfd pfd = { .fd = 0, .events = 0, .revents = 0 }; 31*aca3beaaSApple OSS Distributions 32*aca3beaaSApple OSS Distributions begin_time = mach_absolute_time(); 33*aca3beaaSApple OSS Distributions sleep(SLEEP_TIME_SECS); 34*aca3beaaSApple OSS Distributions sleep_time = mach_absolute_time() - begin_time; 35*aca3beaaSApple OSS Distributions T_LOG("sleep(%d) ~= %llu mach absolute time units", SLEEP_TIME_SECS, sleep_time); 36*aca3beaaSApple OSS Distributions 37*aca3beaaSApple OSS Distributions begin_time = mach_absolute_time(); 38*aca3beaaSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(poll(&pfd, 0, POLL_TIMEOUT_MS), 39*aca3beaaSApple OSS Distributions "poll() with 0 events and timeout %d ms", POLL_TIMEOUT_MS); 40*aca3beaaSApple OSS Distributions poll_time = mach_absolute_time() - begin_time; 41*aca3beaaSApple OSS Distributions 42*aca3beaaSApple OSS Distributions T_EXPECT_GT(poll_time, sleep_time, 43*aca3beaaSApple OSS Distributions "poll(... %d) should wait longer than sleep(1)", POLL_TIMEOUT_MS); 44*aca3beaaSApple OSS Distributions } 45*aca3beaaSApple OSS Distributions 46*aca3beaaSApple OSS Distributions #define LAUNCHD_PATH "/sbin/launchd" 47*aca3beaaSApple OSS Distributions #define PIPE_DIR_TIMEOUT_SECS 1 48*aca3beaaSApple OSS Distributions 49*aca3beaaSApple OSS Distributions /* 50*aca3beaaSApple OSS Distributions * See <rdar://problem/28539155>. 51*aca3beaaSApple OSS Distributions */ 52*aca3beaaSApple OSS Distributions T_DECL(directories, 53*aca3beaaSApple OSS Distributions "poll() with directories should return an error") 54*aca3beaaSApple OSS Distributions { 55*aca3beaaSApple OSS Distributions int file, dir, pipes[2]; 56*aca3beaaSApple OSS Distributions struct pollfd pfd[] = { 57*aca3beaaSApple OSS Distributions { .events = POLLIN }, 58*aca3beaaSApple OSS Distributions { .events = POLLIN }, 59*aca3beaaSApple OSS Distributions { .events = POLLIN }, 60*aca3beaaSApple OSS Distributions }; 61*aca3beaaSApple OSS Distributions 62*aca3beaaSApple OSS Distributions file = open(LAUNCHD_PATH, O_RDONLY | O_NONBLOCK); 63*aca3beaaSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(file, "open(%s)", LAUNCHD_PATH); 64*aca3beaaSApple OSS Distributions dir = open(".", O_RDONLY | O_NONBLOCK); 65*aca3beaaSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(dir, "open(\".\")"); 66*aca3beaaSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(pipe(pipes), NULL); 67*aca3beaaSApple OSS Distributions 68*aca3beaaSApple OSS Distributions /* just directory */ 69*aca3beaaSApple OSS Distributions pfd[0].fd = dir; 70*aca3beaaSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(poll(pfd, 1, -1), "poll() with a directory"); 71*aca3beaaSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLNVAL, 72*aca3beaaSApple OSS Distributions "directory should be an invalid event"); 73*aca3beaaSApple OSS Distributions 74*aca3beaaSApple OSS Distributions /* file and directory */ 75*aca3beaaSApple OSS Distributions pfd[0].fd = file; pfd[0].revents = 0; 76*aca3beaaSApple OSS Distributions pfd[1].fd = dir; pfd[1].revents = 0; 77*aca3beaaSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(poll(pfd, 2, -1), 78*aca3beaaSApple OSS Distributions "poll() with a file and directory"); 79*aca3beaaSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLIN, "file should be readable"); 80*aca3beaaSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[1].revents & POLLNVAL, 81*aca3beaaSApple OSS Distributions "directory should be an invalid event"); 82*aca3beaaSApple OSS Distributions 83*aca3beaaSApple OSS Distributions /* directory and file */ 84*aca3beaaSApple OSS Distributions pfd[0].fd = dir; pfd[0].revents = 0; 85*aca3beaaSApple OSS Distributions pfd[1].fd = file; pfd[1].revents = 0; 86*aca3beaaSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(poll(pfd, 2, -1), 87*aca3beaaSApple OSS Distributions "poll() with a directory and a file"); 88*aca3beaaSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLNVAL, 89*aca3beaaSApple OSS Distributions "directory should be an invalid event"); 90*aca3beaaSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[1].revents & POLLIN, "file should be readable"); 91*aca3beaaSApple OSS Distributions 92*aca3beaaSApple OSS Distributions /* file and pipe */ 93*aca3beaaSApple OSS Distributions pfd[0].fd = file; pfd[0].revents = 0; 94*aca3beaaSApple OSS Distributions pfd[1].fd = pipes[0]; pfd[0].revents = 0; 95*aca3beaaSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(poll(pfd, 2, -1), 96*aca3beaaSApple OSS Distributions "poll() with a file and pipe"); 97*aca3beaaSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLIN, "file should be readable"); 98*aca3beaaSApple OSS Distributions T_QUIET; T_EXPECT_FALSE(pfd[1].revents & POLLIN, 99*aca3beaaSApple OSS Distributions "pipe should not be readable"); 100*aca3beaaSApple OSS Distributions 101*aca3beaaSApple OSS Distributions /* file, directory, and pipe */ 102*aca3beaaSApple OSS Distributions pfd[0].fd = file; pfd[0].revents = 0; 103*aca3beaaSApple OSS Distributions pfd[1].fd = dir; pfd[1].revents = 0; 104*aca3beaaSApple OSS Distributions pfd[2].fd = pipes[0]; pfd[2].revents = 0; 105*aca3beaaSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(poll(pfd, 3, -1), 106*aca3beaaSApple OSS Distributions "poll() with a file, directory, and pipe"); 107*aca3beaaSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLIN, "file should be readable"); 108*aca3beaaSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[1].revents & POLLNVAL, 109*aca3beaaSApple OSS Distributions "directory should be an invalid event"); 110*aca3beaaSApple OSS Distributions T_QUIET; T_EXPECT_FALSE(pfd[2].revents & POLLIN, "pipe should not be readable"); 111*aca3beaaSApple OSS Distributions 112*aca3beaaSApple OSS Distributions /* directory and pipe */ 113*aca3beaaSApple OSS Distributions __block bool timed_out = true; 114*aca3beaaSApple OSS Distributions pfd[0].fd = dir; pfd[0].revents = 0; 115*aca3beaaSApple OSS Distributions pfd[1].fd = pipes[0]; pfd[1].revents = 0; 116*aca3beaaSApple OSS Distributions dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 117*aca3beaaSApple OSS Distributions PIPE_DIR_TIMEOUT_SECS * NSEC_PER_SEC), 118*aca3beaaSApple OSS Distributions dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{ 119*aca3beaaSApple OSS Distributions T_ASSERT_FALSE(timed_out, "poll timed out after %d seconds", 120*aca3beaaSApple OSS Distributions PIPE_DIR_TIMEOUT_SECS); 121*aca3beaaSApple OSS Distributions }); 122*aca3beaaSApple OSS Distributions 123*aca3beaaSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(poll(pfd, 3, -1), 124*aca3beaaSApple OSS Distributions "poll() with a directory and pipe"); 125*aca3beaaSApple OSS Distributions timed_out = false; 126*aca3beaaSApple OSS Distributions 127*aca3beaaSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLNVAL, 128*aca3beaaSApple OSS Distributions "directory should be an invalid event"); 129*aca3beaaSApple OSS Distributions T_QUIET; T_EXPECT_FALSE(pfd[1].revents & POLLIN, "pipe should not be readable"); 130*aca3beaaSApple OSS Distributions } 131