mirror of
https://github.com/darlinghq/darling-xnu.git
synced 2024-11-23 12:39:55 +00:00
80 lines
1.6 KiB
C
80 lines
1.6 KiB
C
#include <unistd.h>
|
|
#include <pthread.h>
|
|
#include <errno.h>
|
|
|
|
#include <sys/event.h>
|
|
|
|
#include <darwintest.h>
|
|
|
|
T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
|
|
|
|
/*
|
|
* <rdar://problem/30231213> close() of kqueue FD races with kqueue_scan park
|
|
*
|
|
* When close concurrent with poll goes wrong, the close hangs
|
|
* and the kevent never gets any more events.
|
|
*/
|
|
|
|
/* Both events should fire at about the same time */
|
|
static uint32_t timeout_ms = 10;
|
|
|
|
static void *
|
|
poll_kqueue(void *arg)
|
|
{
|
|
int fd = (int)arg;
|
|
|
|
struct kevent kev = {
|
|
.filter = EVFILT_TIMER,
|
|
.flags = EV_ADD,
|
|
.data = timeout_ms,
|
|
};
|
|
|
|
int rv = kevent(fd, &kev, 1, NULL, 0, NULL);
|
|
|
|
if (rv == -1 && errno == EBADF) {
|
|
/* The close may race with this thread spawning */
|
|
T_LOG("kqueue already closed?");
|
|
return NULL;
|
|
} else {
|
|
T_QUIET; T_ASSERT_POSIX_SUCCESS(rv, "kevent");
|
|
}
|
|
|
|
while ((rv = kevent(fd, NULL, 0, &kev, 1, NULL)) == 1) {
|
|
T_LOG("poll\n");
|
|
}
|
|
|
|
if (rv != -1 || errno != EBADF) {
|
|
T_ASSERT_POSIX_SUCCESS(rv, "fd should be closed");
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
run_test()
|
|
{
|
|
int fd = kqueue();
|
|
T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, "kqueue");
|
|
|
|
pthread_t thread;
|
|
int rv = pthread_create(&thread, NULL, poll_kqueue,
|
|
(void *)(uintptr_t)fd);
|
|
T_QUIET; T_ASSERT_POSIX_SUCCESS(rv, "pthread_create");
|
|
|
|
usleep(timeout_ms * 1000);
|
|
|
|
rv = close(fd);
|
|
T_ASSERT_POSIX_SUCCESS(rv, "close");
|
|
|
|
rv = pthread_join(thread, NULL);
|
|
T_QUIET; T_ASSERT_POSIX_SUCCESS(rv, "pthread_join");
|
|
}
|
|
|
|
T_DECL(kqueue_close_race, "Races kqueue close with kqueue process",
|
|
T_META_LTEPHASE(LTE_POSTINIT), T_META_TIMEOUT(5))
|
|
{
|
|
for (uint32_t i = 1; i < 100; i++) {
|
|
run_test();
|
|
}
|
|
}
|