1

I'm monitoring list of socket fds and wait POLLIN events.

First I add fds to array and run poll() on this array. Further, in some cases I want to delete fd from this array(without closing). And sometimes it may occurs concurrently with poll() was running.

As I understood when poll() starting, kernel cached array with waitering pollfds, so it cannot to be able know that I delete fd immediately, right?

I found that we can to implement wakeup mechanism with eventfd() and use it for wake up our thread and delete fd from array, and after continue run poll() with new array.

First I want to ask that is it correct, that poll() not be know immediately if we will just delete fd from pollfds array concurrently with poll() running? And it's more for clarifying, maybe there some different mechanism for deleting fd from waitering pollfds array (excluding wakeup mechanism), that poll() will be interrupt immediately?

Obsidian
  • 3,719
  • 8
  • 17
  • 30
adanos911
  • 11
  • 2
  • 1
    If I understand what you're trying to do correctly, epoll is a better interface for it. – Shawn Nov 15 '20 at 15:01

1 Answers1

1

The poll syscall first copies the user-provided list of fds to kernel buffers before it starts checking for updates to these files. In short, this means that you will not be able to change the list of fds from a concurrent thread, and that a syscall waiting on this list will not wake up immediately if you write to the argument pollfds array.

The relevant code for this syscall is in the do_sys_poll function (https://elixir.bootlin.com/linux/v5.11/source/fs/select.c#L970). The walk is a kernel list of buffers holding a copy of the user provided list of fds ufds. During the for-loop within lines 987-1008, the kernel incrementally copies the array of fds from ufds. Any concurrent writes from threads before or during this state can change the values in walk. After the copy, the kernel calls do_poll which actually performs the job of the syscall, checking for updates to these fds. Any concurrent to ufds during this period updates the userspace buffer, but not the kernel version. The kernel will never see these updates, and will therefore never ignore any fds you 'delete' from this list (assuming you mean you set the fd to negative).

TSG
  • 877
  • 1
  • 6
  • 23