On 10/16/26 12:13 AM, Terry Wilson via dev wrote: > This looks reasonable to me. I've tested ovsdbapp functional tests, > neutron master functional tests and a tempest API test run, and some > older stable/2024.1 neutron functional tests and see no failure > differences. Importing pre-eventlet removal neutron code and running > poller._get_poll() returns in _SelectSelect and in newer neutron I > verified it return select.poll. > > Acked-by: Terry Wilson <[email protected]> > Tested-by: Terry Wilson <[email protected]> > > On Thu, Sep 17, 2026 at 9:38 AM 이규영 <[email protected]> wrote: >> >> From: Kyuyeong Lee <[email protected]> >> Date: Thu, 17 Sep 2026 20:00:33 +0900 >> Subject: [PATCH v3] python: poller: Use poll(2) instead of select(2). >> >> Poller has always allocated SelectPoll, that is _SelectSelect, which >> emulates poll(2) on top of select.select. The comment above it offers to >> swap in select.poll by hand when eventlet and gevent are not in use, but >> the name it mentions, _SelectPoll, does not exist anywhere in the tree, so >> uncommenting that line has no effect. >> >> Emulating poll(2) with the real select(2) is not merely slower. select(2) >> cannot represent a file descriptor numbered FD_SETSIZE (1024) or higher, >> and Python raises >> >> ValueError: filedescriptor out of range in select() >> >> instead of corrupting the fd_set. A long lived process that holds more >> than a thousand file descriptors therefore breaks as soon as a descriptor >> the poller watches lands above the limit, for example when a connection is >> re-established late in the process lifetime. Poller.block() does not catch >> ValueError, so it reaches the caller, and a caller that retries its loop >> spins on a full CPU from then on. >> >> This has been masked for eventlet users, which is most of them: eventlet >> replaces select.select with eventlet.green.select, which multiplexes >> through the hub and has no FD_SETSIZE limit. As OpenStack removes its >> eventlet dependency the emulation starts calling the real select(2) and the >> limit applies. It was hit in production in a neutron-server whose API >> workers each held around 1200 file descriptors: the OVSDB connection thread >> wedged permanently at 100% CPU and every later transaction in that worker >> failed until the process was restarted. >> >> Use poll(2), which has no FD_SETSIZE limit, and keep the emulation where >> select.select is green. There it is not subject to the limit either, and >> the real poll(2) would block the whole interpreter rather than yield to the >> other greenlets, which is precisely what the emulation exists to avoid. >> >> get_system_poll() cannot be reused here. It deliberately returns the >> original, blocking poll under eventlet, which is what the non-blocking >> poll(0) probe in socket_util.check_connection_completion() wants, but not >> what Poller.block() needs. >> >> Signed-off-by: Kyuyeong Lee <[email protected]> >> --- >> v2: No code change. Resent with an in-body From: line so that the author >> matches the Signed-off-by; our mail gateway rewrites the display name >> in the From header. >> v3: No code change. v2 was mangled in transit, the tabs in >> python/automake.mk were turned into spaces. Resent after checking >> that they survive this time. >> >> python/automake.mk | 3 ++- >> python/ovs/poller.py | 22 ++++++++++++++--- >> python/ovs/tests/test_poller.py | 44 +++++++++++++++++++++++++++++++++ >> 3 files changed, 64 insertions(+), 5 deletions(-) >> create mode 100644 python/ovs/tests/test_poller.py
Thanks, Kyuyeong, for the patch and thanks, Terry, for testing. While the old code suggested that the select.poll() can be used as a drop-in replacement, it is not really the case, it seems. The problem is that a second select.poll.register() call overwrites the event flags for the file descriptor. So, if we first register for POLLOUT and then for POLLIN, then we will not actually wait for POLLOUT, which may be a problem on a congested connection where the application will never wake up to send if there is nothing to receive. We may need to have a separate class similar to the _SelectSelect to accumulate the flags and only actually register in the poll() call itself when we have all the event flags. WDYT? Best regards, Ilya Maximets. _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
