I have an event descriptor that was created in C code like this:
int notifyED = eventfd(0, EFD_SEMAPHORE | EFD_CLOEXEC);
The counter goes up and down as expected as a result of calls to eventfd_read() and eventfd_write().
All good so far. Now I want to "flush" the 64-bit counter within this event FD so that it resets to zero.
The flush operation needs to be "transparent" to any poll/epoll instance that is monitoring the event FD.
After the flush, any polling instance should not generate a new POLLIN until a further
eventfd_write()happens.
Obviously the semaphore-like semantics will prevent the counter being reset in a single read() operation, so I have implemented the flush this way:
int flushED = eventfd(0, EFD_SEMAPHORE);
notifyED = dup3(flushED, notifyED, O_CLOEXEC);
close(flushED);
If I understand the documentation pages for dup() and its variants correctly, dup3() should atomically close and reassign the event descriptor. N.B. the program always explicitly calls close(notifyED) before it exits.
EDIT: updated to use dup3() to maintain the CLOEXEC flag and to incorporate feedback in comments about closing both descriptors.
Alternative solutions I am already aware of:
for epoll specifically, use ctl_add() and ctl_del() to replace the descriptor with a new one;
repeatedly call
eventfd_read()until the counter is zero.
Specific questions:
Is the
dup3()approach acceptable ?Am I leaking descriptor resources at all ?
From my testing, an epoll instance seems to behave as expected. Any gotchas I have missed ?