[Python-checkins] bpo-41182 selector: use DefaultSelector based upon implementation (GH-21257)

Abhijeet Kasurde webhook-mailer at python.org
Wed Jul 22 23:13:45 EDT 2020


https://github.com/python/cpython/commit/bcd47837a9bf4806e559b40df73869493efcce27
commit: bcd47837a9bf4806e559b40df73869493efcce27
branch: master
author: Abhijeet Kasurde <akasurde at redhat.com>
committer: GitHub <noreply at github.com>
date: 2020-07-22T20:13:37-07:00
summary:

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 at redhat.com>

files:
A Misc/NEWS.d/next/Library/2020-07-01-17-33-50.bpo-41182.FPFI0N.rst
M Lib/selectors.py

diff --git a/Lib/selectors.py b/Lib/selectors.py
index 90251dc34a0b3..bb15a1cb1bada 100644
--- a/Lib/selectors.py
+++ b/Lib/selectors.py
@@ -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."""
 
@@ -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
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 0000000000000..ae31db512abdc
--- /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



More information about the Python-checkins mailing list