Skip to content

Instantly share code, notes, and snippets.

@prattmic
Last active December 17, 2020 16:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prattmic/8b5bc6c87437bd4496d5f546fb3226fc to your computer and use it in GitHub Desktop.
Save prattmic/8b5bc6c87437bd4496d5f546fb3226fc to your computer and use it in GitHub Desktop.
// $ gcc -pthread kqueue_race.c
// $ ./a.out
// kevent = 0
// Incorrect number of events after 477 calls!
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/event.h>
#include <sys/time.h>
#include <unistd.h>
int kq;
void* read_kevent(void* arg) {
int count = 0;
while (1) {
count++;
// Non-blocking.
struct timespec ts = {};
struct kevent ev;
int n = kevent(kq, NULL, 0, &ev, 1, &ts);
if (n < 0) {
perror("kevent");
exit(1);
} else if (n != 1) {
printf("kevent = %d\n", n);
printf("Incorrect number of events after %d calls!\n", count);
exit(2);
}
}
}
int main(int argc, char** argv) {
int p[2];
int ret = pipe(p);
if (ret < 0) {
perror("pipe");
return 1;
}
kq = kqueue();
if (kq < 0) {
perror("kqueue");
return 1;
}
struct kevent ev = {};
EV_SET(&ev, p[0], EVFILT_READ, EV_ADD, 0, 0, 0);
ret = kevent(kq, &ev, 1, NULL, 0, NULL);
if (ret < 0) {
perror("kevent register");
return 1;
}
// Write to pipe, kevent now ready for read end.
char c = 0;
ret = write(p[1], &c, 1);
if (ret != 1) {
perror("write");
return 1;
}
pthread_t t1, t2;
ret = pthread_create(&t1, NULL, read_kevent, NULL);
if (ret < 0) {
perror("pthread_create");
return 1;
}
ret = pthread_create(&t2, NULL, read_kevent, NULL);
if (ret < 0) {
perror("pthread_create");
return 1;
}
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment