12 volatile int started, done, handled;
15 unsigned char bytes[256];
17static struct reader* active_reader;
18static void handler(
int signal) {
21 __atomic_add_fetch(&active_reader->handled, 1, __ATOMIC_RELEASE);
23static void* read_thread(
void* argument) {
25 __atomic_store_n(&
reader->started, 1, __ATOMIC_RELEASE);
29 __atomic_store_n(&
reader->done, 1, __ATOMIC_RELEASE);
33static int interrupted(
int restart) {
34 int failed = 0, group = -1, running = 0, installed = 0;
37 struct sigaction old, action = {.sa_handler = handler, .sa_flags = restart ? SA_RESTART : 0};
38 struct fh_file file = {.fd = -1};
40 CHECK(!fh_create(&file));
42 CHECK(group >= 0 && !fh_mark(group, &file, FAN_MARK_ADD, FAN_MODIFY));
44 reader.size = fh_record_size(&file.handle);
45 sigemptyset(&action.sa_mask);
46 CHECK(!sigaction(SIGUSR1, &action, &old));
49 CHECK(!pthread_create(&thread, NULL, read_thread, &
reader));
51 CHECK(!fh_wait(&
reader.started, 2000));
52 int64_t deadline = fh_now() + 5000000000;
53 while (!__atomic_load_n(&
reader.done, __ATOMIC_ACQUIRE) && fh_now() < deadline) {
54 CHECK(!pthread_kill(thread, SIGUSR1));
55 if (restart && __atomic_load_n(&
reader.handled, __ATOMIC_ACQUIRE) >= 3)
59 CHECK(__atomic_load_n(&
reader.handled, __ATOMIC_ACQUIRE) > 0);
61 CHECK(!__atomic_load_n(&
reader.done, __ATOMIC_ACQUIRE));
62 CHECK(!fh_modify(&file));
63 CHECK(!fh_wait(&
reader.done, 5000));
65 !fh_parse(
reader.bytes, (
size_t)
reader.result, &record));
66 CHECK(record.mask == FAN_MODIFY && record.pid == getpid() &&
67 fh_equal(&record.handle, &file.handle));
69 CHECK(!fh_wait(&
reader.done, 100));
71 CHECK(!fh_modify(&file));
72 CHECK(!fh_event(group, &file, FAN_MODIFY, getpid()));
74 CHECK(!pthread_join(thread, NULL));
80 if (fh_wait(&
reader.done, 5000)) {
81 fprintf(stderr,
"FANOTIFY-HANDLE-CONTRACT: reader did not retire result=%ld errno=%d\n",
85 pthread_join(thread, NULL);
89 sigaction(SIGUSR1, &old, NULL);
94static int last_close(
void) {
95 int failed = 0, group = -1, running = 0;
98 struct fh_file file = {.fd = -1};
99 CHECK(!fh_create(&file));
103 reader.size = fh_record_size(&file.handle);
104 CHECK(!pthread_create(&thread, NULL, read_thread, &
reader));
106 CHECK(!fh_wait(&
reader.started, 2000));
107 CHECK(!close(group));
109 CHECK(!fh_wait(&
reader.done, 5000));
111 CHECK(!pthread_join(thread, NULL));
117 if (fh_wait(&
reader.done, 5000))
119 pthread_join(thread, NULL);
125 return interrupted(0) || interrupted(1) || last_close();