]> git.saurik.com Git - apple/xnu.git/blob - tests/fd.c
7f58a64e813385334b05f2552d1a39be2b99ed17
[apple/xnu.git] / tests / fd.c
1 #include <darwintest.h>
2 #include <darwintest_utils.h>
3 #include <pthread.h>
4 #include <sys/select.h>
5
6 T_GLOBAL_META(
7 T_META_RUN_CONCURRENTLY(true),
8 T_META_LTEPHASE(LTE_POSTINIT)
9 );
10
11 static void *
12 fd_select_close_helper(void *ctx)
13 {
14 int fd = *(int *)ctx;
15
16 // wait for the thread to enter select
17 usleep(500000);
18 close(fd);
19
20 return NULL;
21 }
22
23 T_DECL(fd_select_close, "Test for 54795873: make sure close breaks out of select")
24 {
25 fd_set read_fd;
26 int pair[2], rc;
27 pthread_t th;
28
29 rc = socketpair(PF_LOCAL, SOCK_STREAM, 0, pair);
30 T_ASSERT_POSIX_SUCCESS(rc, "socketpair");
31
32 pthread_create(&th, NULL, fd_select_close_helper, pair);
33
34 FD_ZERO(&read_fd);
35 FD_SET(pair[0], &read_fd);
36
37 rc = select(pair[0] + 1, &read_fd, NULL, NULL, NULL);
38 T_EXPECT_POSIX_FAILURE(rc, EBADF, "select broke out with EBADF");
39 }
40
41 static void *
42 fd_stress_dup2_close_fun(void *ctx)
43 {
44 int thno = (int)(long)ctx;
45 int count = 10000, rc;
46
47 for (int i = 1; i <= count; i++) {
48 rc = dup2(STDIN_FILENO, 42);
49 T_QUIET; T_EXPECT_POSIX_SUCCESS(rc, "dup2(%d, 42)", STDIN_FILENO);
50 if (thno == 3) {
51 rc = close(42);
52 if (rc == -1) {
53 T_QUIET; T_EXPECT_POSIX_FAILURE(rc, EBADF, "close(42)");
54 }
55 }
56 if (i % 1000 == 0) {
57 T_LOG("thread %d: %d/%d dups\n", thno, i, count);
58 }
59 }
60
61 return NULL;
62 }
63
64 T_DECL(fd_stress_dup2_close, "Stress test races between dup2 and close")
65 {
66 pthread_t th[4];
67 int rc;
68
69 for (int i = 0; i < 4; i++) {
70 rc = pthread_create(&th[i], NULL,
71 fd_stress_dup2_close_fun, (void *)(long)i);
72 T_ASSERT_POSIX_ZERO(rc, "pthread_create");
73 }
74
75 for (int i = 0; i < 4; i++) {
76 pthread_join(th[i], NULL);
77 }
78 }
79
80 T_DECL(fd_dup2_erase_clofork_58446996,
81 "Make sure dup2() doesn't inherit flags from an old fd")
82 {
83 int fd1, fd2;
84
85 fd1 = open("/dev/null", O_RDONLY | O_CLOEXEC);
86 T_ASSERT_POSIX_SUCCESS(fd1, "open(/dev/null)");
87
88 fd2 = open("/dev/null", O_RDONLY | O_CLOEXEC);
89 T_ASSERT_POSIX_SUCCESS(fd2, "open(/dev/null)");
90
91 T_ASSERT_POSIX_SUCCESS(dup2(fd1, fd2), "dup2(fd1, fd2)");
92 T_EXPECT_EQ(fcntl(fd2, F_GETFD, 0), 0,
93 "neither FD_CLOEXEC nor FD_CLOFORK should be set");
94 }