summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbhijeet Kasurde <akasurde@redhat.com>2020-07-23 03:13:37 (GMT)
committerGitHub <noreply@github.com>2020-07-23 03:13:37 (GMT)
commitbcd47837a9bf4806e559b40df73869493efcce27 (patch)
treee6c95e6ba02927266ed7ab30918b62bfed9d8253
parentb9f6ac9d463b3c5823197b0bde3869876f65f413 (diff)
downloadcpython-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.py32
-rw-r--r--Misc/NEWS.d/next/Library/2020-07-01-17-33-50.bpo-41182.FPFI0N.rst1
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