How to reset a Linux event descriptor created with EFD_SEMAPHORE

146 views Asked by At

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:

  1. for epoll specifically, use ctl_add() and ctl_del() to replace the descriptor with a new one;

  2. repeatedly call eventfd_read() until the counter is zero.

Specific questions:

  1. Is the dup3() approach acceptable ?

  2. Am I leaking descriptor resources at all ?

  3. From my testing, an epoll instance seems to behave as expected. Any gotchas I have missed ?

0

There are 0 answers