]> git.saurik.com Git - apple/xnu.git/blame_incremental - tools/tests/darwintests/kqueue_close.c
xnu-4570.51.1.tar.gz
[apple/xnu.git] / tools / tests / darwintests / kqueue_close.c
... / ...
CommitLineData
1#include <unistd.h>
2#include <pthread.h>
3#include <errno.h>
4
5#include <sys/event.h>
6
7#include <darwintest.h>
8
9/*
10 * <rdar://problem/30231213> close() of kqueue FD races with kqueue_scan park
11 *
12 * When close concurrent with poll goes wrong, the close hangs
13 * and the kevent never gets any more events.
14 */
15
16/* Both events should fire at about the same time */
17static uint32_t timeout_ms = 10;
18
19static void *
20poll_kqueue(void *arg)
21{
22 int fd = (int)arg;
23
24 struct kevent kev = {
25 .filter = EVFILT_TIMER,
26 .flags = EV_ADD,
27 .data = timeout_ms,
28 };
29
30 int rv = kevent(fd, &kev, 1, NULL, 0, NULL);
31
32 if (rv == -1 && errno == EBADF) {
33 /* The close may race with this thread spawning */
34 T_LOG("kqueue already closed?");
35 return NULL;
36 } else {
37 T_QUIET; T_ASSERT_POSIX_SUCCESS(rv, "kevent");
38 }
39
40 while ((rv = kevent(fd, NULL, 0, &kev, 1, NULL)) == 1) {
41 T_LOG("poll\n");
42 }
43
44 if (rv != -1 || errno != EBADF) {
45 T_ASSERT_POSIX_SUCCESS(rv, "fd should be closed");
46 }
47
48 return NULL;
49}
50
51static void
52run_test()
53{
54 int fd = kqueue();
55 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, "kqueue");
56
57 pthread_t thread;
58 int rv = pthread_create(&thread, NULL, poll_kqueue,
59 (void *)(uintptr_t)fd);
60 T_QUIET; T_ASSERT_POSIX_SUCCESS(rv, "pthread_create");
61
62 usleep(timeout_ms * 1000);
63
64 rv = close(fd);
65 T_ASSERT_POSIX_SUCCESS(rv, "close");
66
67 rv = pthread_join(thread, NULL);
68 T_QUIET; T_ASSERT_POSIX_SUCCESS(rv, "pthread_join");
69}
70
71T_DECL(kqueue_close_race, "Races kqueue close with kqueue process",
72 T_META_LTEPHASE(LTE_POSTINIT), T_META_TIMEOUT(5))
73{
74 for (uint32_t i = 1 ; i < 100 ; i++) {
75 run_test();
76 }
77}