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