Skip to content

Commit

Permalink
bpo-41182 selector: use DefaultSelector based upon implementation (py…
Browse files Browse the repository at this point in the history
…thonGH-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]>
  • Loading branch information
Akasurde authored Jul 23, 2020
1 parent b9f6ac9 commit bcd4783
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 4 deletions.
32 changes: 28 additions & 4 deletions Lib/selectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def _fileobj_to_fd(fileobj):
SelectorKey.data.__doc__ = ('''Optional opaque data associated to this file object.
For example, this could be used to store a per-client session ID.''')


class _SelectorMapping(Mapping):
"""Mapping of file objects to selector keys."""

Expand Down Expand Up @@ -580,16 +581,39 @@ def close(self):
super().close()


def _can_use(method):
"""Check if we can use the selector depending upon the
operating system. """
# Implementation based upon https://github.com/sethmlarson/selectors2/blob/master/selectors2.py
selector = getattr(select, method, None)
if selector is None:
# select module does not implement method
return False
# check if the OS and Kernel actually support the method. Call may fail with
# OSError: [Errno 38] Function not implemented
try:
selector_obj = selector()
if method == 'poll':
# check that poll actually works
selector_obj.poll(0)
else:
# close epoll, kqueue, and devpoll fd
selector_obj.close()
return True
except OSError:
return False


# Choose the best implementation, roughly:
# epoll|kqueue|devpoll > poll > select.
# select() also can't accept a FD > FD_SETSIZE (usually around 1024)
if 'KqueueSelector' in globals():
if _can_use('kqueue'):
DefaultSelector = KqueueSelector
elif 'EpollSelector' in globals():
elif _can_use('epoll'):
DefaultSelector = EpollSelector
elif 'DevpollSelector' in globals():
elif _can_use('devpoll'):
DefaultSelector = DevpollSelector
elif 'PollSelector' in globals():
elif _can_use('poll'):
DefaultSelector = PollSelector
else:
DefaultSelector = SelectSelector
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
selector: use DefaultSelector based upon implementation

0 comments on commit bcd4783

Please sign in to comment.