Skip to content

Commit bcd4783

Browse files
authored
bpo-41182 selector: use DefaultSelector based upon implementation (GH-21257)
On some platform such as VMware ESXi, DefaultSelector fails to detect selector due to default value. This fix adds a check and uses the correct selector depending upon select implementation and actual call. Fixes: [bpo-41182]() Signed-off-by: Abhijeet Kasurde <[email protected]>
1 parent b9f6ac9 commit bcd4783

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

Lib/selectors.py

+28-4
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ def _fileobj_to_fd(fileobj):
5757
SelectorKey.data.__doc__ = ('''Optional opaque data associated to this file object.
5858
For example, this could be used to store a per-client session ID.''')
5959

60+
6061
class _SelectorMapping(Mapping):
6162
"""Mapping of file objects to selector keys."""
6263

@@ -580,16 +581,39 @@ def close(self):
580581
super().close()
581582

582583

584+
def _can_use(method):
585+
"""Check if we can use the selector depending upon the
586+
operating system. """
587+
# Implementation based upon https://github.com/sethmlarson/selectors2/blob/master/selectors2.py
588+
selector = getattr(select, method, None)
589+
if selector is None:
590+
# select module does not implement method
591+
return False
592+
# check if the OS and Kernel actually support the method. Call may fail with
593+
# OSError: [Errno 38] Function not implemented
594+
try:
595+
selector_obj = selector()
596+
if method == 'poll':
597+
# check that poll actually works
598+
selector_obj.poll(0)
599+
else:
600+
# close epoll, kqueue, and devpoll fd
601+
selector_obj.close()
602+
return True
603+
except OSError:
604+
return False
605+
606+
583607
# Choose the best implementation, roughly:
584608
# epoll|kqueue|devpoll > poll > select.
585609
# select() also can't accept a FD > FD_SETSIZE (usually around 1024)
586-
if 'KqueueSelector' in globals():
610+
if _can_use('kqueue'):
587611
DefaultSelector = KqueueSelector
588-
elif 'EpollSelector' in globals():
612+
elif _can_use('epoll'):
589613
DefaultSelector = EpollSelector
590-
elif 'DevpollSelector' in globals():
614+
elif _can_use('devpoll'):
591615
DefaultSelector = DevpollSelector
592-
elif 'PollSelector' in globals():
616+
elif _can_use('poll'):
593617
DefaultSelector = PollSelector
594618
else:
595619
DefaultSelector = SelectSelector
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
selector: use DefaultSelector based upon implementation

0 commit comments

Comments
 (0)