diff options
author | Abhijeet Kasurde <akasurde@redhat.com> | 2020-07-23 03:13:37 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-23 03:13:37 (GMT) |
commit | bcd47837a9bf4806e559b40df73869493efcce27 (patch) | |
tree | e6c95e6ba02927266ed7ab30918b62bfed9d8253 | |
parent | b9f6ac9d463b3c5823197b0bde3869876f65f413 (diff) | |
download | cpython-bcd47837a9bf4806e559b40df73869493efcce27.zip cpython-bcd47837a9bf4806e559b40df73869493efcce27.tar.gz cpython-bcd47837a9bf4806e559b40df73869493efcce27.tar.bz2 |
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 <akasurde@redhat.com>
-rw-r--r-- | Lib/selectors.py | 32 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2020-07-01-17-33-50.bpo-41182.FPFI0N.rst | 1 |
2 files changed, 29 insertions, 4 deletions
diff --git a/Lib/selectors.py b/Lib/selectors.py index 90251dc..bb15a1c 100644 --- a/Lib/selectors.py +++ b/Lib/selectors.py @@ -57,6 +57,7 @@ if sys.version_info >= (3, 5): 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.""" @@ -580,16 +581,39 @@ if hasattr(select, 'kqueue'): 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 diff --git a/Misc/NEWS.d/next/Library/2020-07-01-17-33-50.bpo-41182.FPFI0N.rst b/Misc/NEWS.d/next/Library/2020-07-01-17-33-50.bpo-41182.FPFI0N.rst new file mode 100644 index 0000000..ae31db5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-07-01-17-33-50.bpo-41182.FPFI0N.rst @@ -0,0 +1 @@ +selector: use DefaultSelector based upon implementation |