comparison mercurial/selectors2.py @ 33502:5d0c0c8d2929

selector2: vendor selector2 library This library was a backport of the Python 3 "selectors" library. It is useful to provide a better selector interface for Python2, to address some issues of the plain old select.select, mentioned in the next patch. The code [1] was ported using the MIT license, with some minor modifications to make our test happy: 1. "# no-check-code" was added since it's foreign code. 2. "from __future__ import absolute_import" was added. 3. "from collections import namedtuple, Mapping" changed to avoid direct symbol import. [1]: https://github.com/SethMichaelLarson/selectors2/blob/d27dbd2fdc48331fb76ed431f44b6e6956de7f82/selectors2.py # no-check-commit
author Jun Wu <quark@fb.com>
date Fri, 14 Jul 2017 20:19:46 -0700
parents
children a568a46751b6
comparison
equal deleted inserted replaced
33501:7008f6819002 33502:5d0c0c8d2929
1 """ Back-ported, durable, and portable selectors """
2
3 # MIT License
4 #
5 # Copyright (c) 2017 Seth Michael Larson
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be included in all
15 # copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 # SOFTWARE.
24
25 # no-check-code
26
27 from __future__ import absolute_import
28
29 import collections
30 import errno
31 import math
32 import platform
33 import select
34 import socket
35 import sys
36 import time
37
38 namedtuple = collections.namedtuple
39 Mapping = collections.Mapping
40
41 try:
42 monotonic = time.monotonic
43 except AttributeError:
44 monotonic = time.time
45
46 __author__ = 'Seth Michael Larson'
47 __email__ = 'sethmichaellarson@protonmail.com'
48 __version__ = '2.0.0'
49 __license__ = 'MIT'
50 __url__ = 'https://www.github.com/SethMichaelLarson/selectors2'
51
52 __all__ = ['EVENT_READ',
53 'EVENT_WRITE',
54 'SelectorKey',
55 'DefaultSelector',
56 'BaseSelector']
57
58 EVENT_READ = (1 << 0)
59 EVENT_WRITE = (1 << 1)
60 _DEFAULT_SELECTOR = None
61 _SYSCALL_SENTINEL = object() # Sentinel in case a system call returns None.
62 _ERROR_TYPES = (OSError, IOError, socket.error)
63
64
65 SelectorKey = namedtuple('SelectorKey', ['fileobj', 'fd', 'events', 'data'])
66
67
68 class _SelectorMapping(Mapping):
69 """ Mapping of file objects to selector keys """
70
71 def __init__(self, selector):
72 self._selector = selector
73
74 def __len__(self):
75 return len(self._selector._fd_to_key)
76
77 def __getitem__(self, fileobj):
78 try:
79 fd = self._selector._fileobj_lookup(fileobj)
80 return self._selector._fd_to_key[fd]
81 except KeyError:
82 raise KeyError("{0!r} is not registered.".format(fileobj))
83
84 def __iter__(self):
85 return iter(self._selector._fd_to_key)
86
87
88 def _fileobj_to_fd(fileobj):
89 """ Return a file descriptor from a file object. If
90 given an integer will simply return that integer back. """
91 if isinstance(fileobj, int):
92 fd = fileobj
93 else:
94 try:
95 fd = int(fileobj.fileno())
96 except (AttributeError, TypeError, ValueError):
97 raise ValueError("Invalid file object: {0!r}".format(fileobj))
98 if fd < 0:
99 raise ValueError("Invalid file descriptor: {0}".format(fd))
100 return fd
101
102
103 class BaseSelector(object):
104 """ Abstract Selector class
105
106 A selector supports registering file objects to be monitored
107 for specific I/O events.
108
109 A file object is a file descriptor or any object with a
110 `fileno()` method. An arbitrary object can be attached to the
111 file object which can be used for example to store context info,
112 a callback, etc.
113
114 A selector can use various implementations (select(), poll(), epoll(),
115 and kqueue()) depending on the platform. The 'DefaultSelector' class uses
116 the most efficient implementation for the current platform.
117 """
118 def __init__(self):
119 # Maps file descriptors to keys.
120 self._fd_to_key = {}
121
122 # Read-only mapping returned by get_map()
123 self._map = _SelectorMapping(self)
124
125 def _fileobj_lookup(self, fileobj):
126 """ Return a file descriptor from a file object.
127 This wraps _fileobj_to_fd() to do an exhaustive
128 search in case the object is invalid but we still
129 have it in our map. Used by unregister() so we can
130 unregister an object that was previously registered
131 even if it is closed. It is also used by _SelectorMapping
132 """
133 try:
134 return _fileobj_to_fd(fileobj)
135 except ValueError:
136
137 # Search through all our mapped keys.
138 for key in self._fd_to_key.values():
139 if key.fileobj is fileobj:
140 return key.fd
141
142 # Raise ValueError after all.
143 raise
144
145 def register(self, fileobj, events, data=None):
146 """ Register a file object for a set of events to monitor. """
147 if (not events) or (events & ~(EVENT_READ | EVENT_WRITE)):
148 raise ValueError("Invalid events: {0!r}".format(events))
149
150 key = SelectorKey(fileobj, self._fileobj_lookup(fileobj), events, data)
151
152 if key.fd in self._fd_to_key:
153 raise KeyError("{0!r} (FD {1}) is already registered"
154 .format(fileobj, key.fd))
155
156 self._fd_to_key[key.fd] = key
157 return key
158
159 def unregister(self, fileobj):
160 """ Unregister a file object from being monitored. """
161 try:
162 key = self._fd_to_key.pop(self._fileobj_lookup(fileobj))
163 except KeyError:
164 raise KeyError("{0!r} is not registered".format(fileobj))
165
166 # Getting the fileno of a closed socket on Windows errors with EBADF.
167 except socket.error as err:
168 if err.errno != errno.EBADF:
169 raise
170 else:
171 for key in self._fd_to_key.values():
172 if key.fileobj is fileobj:
173 self._fd_to_key.pop(key.fd)
174 break
175 else:
176 raise KeyError("{0!r} is not registered".format(fileobj))
177 return key
178
179 def modify(self, fileobj, events, data=None):
180 """ Change a registered file object monitored events and data. """
181 # NOTE: Some subclasses optimize this operation even further.
182 try:
183 key = self._fd_to_key[self._fileobj_lookup(fileobj)]
184 except KeyError:
185 raise KeyError("{0!r} is not registered".format(fileobj))
186
187 if events != key.events:
188 self.unregister(fileobj)
189 key = self.register(fileobj, events, data)
190
191 elif data != key.data:
192 # Use a shortcut to update the data.
193 key = key._replace(data=data)
194 self._fd_to_key[key.fd] = key
195
196 return key
197
198 def select(self, timeout=None):
199 """ Perform the actual selection until some monitored file objects
200 are ready or the timeout expires. """
201 raise NotImplementedError()
202
203 def close(self):
204 """ Close the selector. This must be called to ensure that all
205 underlying resources are freed. """
206 self._fd_to_key.clear()
207 self._map = None
208
209 def get_key(self, fileobj):
210 """ Return the key associated with a registered file object. """
211 mapping = self.get_map()
212 if mapping is None:
213 raise RuntimeError("Selector is closed")
214 try:
215 return mapping[fileobj]
216 except KeyError:
217 raise KeyError("{0!r} is not registered".format(fileobj))
218
219 def get_map(self):
220 """ Return a mapping of file objects to selector keys """
221 return self._map
222
223 def _key_from_fd(self, fd):
224 """ Return the key associated to a given file descriptor
225 Return None if it is not found. """
226 try:
227 return self._fd_to_key[fd]
228 except KeyError:
229 return None
230
231 def __enter__(self):
232 return self
233
234 def __exit__(self, *_):
235 self.close()
236
237
238 # Almost all platforms have select.select()
239 if hasattr(select, "select"):
240 class SelectSelector(BaseSelector):
241 """ Select-based selector. """
242 def __init__(self):
243 super(SelectSelector, self).__init__()
244 self._readers = set()
245 self._writers = set()
246
247 def register(self, fileobj, events, data=None):
248 key = super(SelectSelector, self).register(fileobj, events, data)
249 if events & EVENT_READ:
250 self._readers.add(key.fd)
251 if events & EVENT_WRITE:
252 self._writers.add(key.fd)
253 return key
254
255 def unregister(self, fileobj):
256 key = super(SelectSelector, self).unregister(fileobj)
257 self._readers.discard(key.fd)
258 self._writers.discard(key.fd)
259 return key
260
261 def select(self, timeout=None):
262 # Selecting on empty lists on Windows errors out.
263 if not len(self._readers) and not len(self._writers):
264 return []
265
266 timeout = None if timeout is None else max(timeout, 0.0)
267 ready = []
268 r, w, _ = _syscall_wrapper(self._wrap_select, True, self._readers,
269 self._writers, timeout)
270 r = set(r)
271 w = set(w)
272 for fd in r | w:
273 events = 0
274 if fd in r:
275 events |= EVENT_READ
276 if fd in w:
277 events |= EVENT_WRITE
278
279 key = self._key_from_fd(fd)
280 if key:
281 ready.append((key, events & key.events))
282 return ready
283
284 def _wrap_select(self, r, w, timeout=None):
285 """ Wrapper for select.select because timeout is a positional arg """
286 return select.select(r, w, [], timeout)
287
288 __all__.append('SelectSelector')
289
290 # Jython has a different implementation of .fileno() for socket objects.
291 if platform.system() == 'Java':
292 class _JythonSelectorMapping(object):
293 """ This is an implementation of _SelectorMapping that is built
294 for use specifically with Jython, which does not provide a hashable
295 value from socket.socket.fileno(). """
296
297 def __init__(self, selector):
298 assert isinstance(selector, JythonSelectSelector)
299 self._selector = selector
300
301 def __len__(self):
302 return len(self._selector._sockets)
303
304 def __getitem__(self, fileobj):
305 for sock, key in self._selector._sockets:
306 if sock is fileobj:
307 return key
308 else:
309 raise KeyError("{0!r} is not registered.".format(fileobj))
310
311 class JythonSelectSelector(SelectSelector):
312 """ This is an implementation of SelectSelector that is for Jython
313 which works around that Jython's socket.socket.fileno() does not
314 return an integer fd value. All SelectorKey.fd will be equal to -1
315 and should not be used. This instead uses object id to compare fileobj
316 and will only use select.select as it's the only selector that allows
317 directly passing in socket objects rather than registering fds.
318 See: http://bugs.jython.org/issue1678
319 https://wiki.python.org/jython/NewSocketModule#socket.fileno.28.29_does_not_return_an_integer
320 """
321
322 def __init__(self):
323 super(JythonSelectSelector, self).__init__()
324
325 self._sockets = [] # Uses a list of tuples instead of dictionary.
326 self._map = _JythonSelectorMapping(self)
327 self._readers = []
328 self._writers = []
329
330 # Jython has a select.cpython_compatible_select function in older versions.
331 self._select_func = getattr(select, 'cpython_compatible_select', select.select)
332
333 def register(self, fileobj, events, data=None):
334 for sock, _ in self._sockets:
335 if sock is fileobj:
336 raise KeyError("{0!r} is already registered"
337 .format(fileobj, sock))
338
339 key = SelectorKey(fileobj, -1, events, data)
340 self._sockets.append((fileobj, key))
341
342 if events & EVENT_READ:
343 self._readers.append(fileobj)
344 if events & EVENT_WRITE:
345 self._writers.append(fileobj)
346 return key
347
348 def unregister(self, fileobj):
349 for i, (sock, key) in enumerate(self._sockets):
350 if sock is fileobj:
351 break
352 else:
353 raise KeyError("{0!r} is not registered.".format(fileobj))
354
355 if key.events & EVENT_READ:
356 self._readers.remove(fileobj)
357 if key.events & EVENT_WRITE:
358 self._writers.remove(fileobj)
359
360 del self._sockets[i]
361 return key
362
363 def _wrap_select(self, r, w, timeout=None):
364 """ Wrapper for select.select because timeout is a positional arg """
365 return self._select_func(r, w, [], timeout)
366
367 __all__.append('JythonSelectSelector')
368 SelectSelector = JythonSelectSelector # Override so the wrong selector isn't used.
369
370
371 if hasattr(select, "poll"):
372 class PollSelector(BaseSelector):
373 """ Poll-based selector """
374 def __init__(self):
375 super(PollSelector, self).__init__()
376 self._poll = select.poll()
377
378 def register(self, fileobj, events, data=None):
379 key = super(PollSelector, self).register(fileobj, events, data)
380 event_mask = 0
381 if events & EVENT_READ:
382 event_mask |= select.POLLIN
383 if events & EVENT_WRITE:
384 event_mask |= select.POLLOUT
385 self._poll.register(key.fd, event_mask)
386 return key
387
388 def unregister(self, fileobj):
389 key = super(PollSelector, self).unregister(fileobj)
390 self._poll.unregister(key.fd)
391 return key
392
393 def _wrap_poll(self, timeout=None):
394 """ Wrapper function for select.poll.poll() so that
395 _syscall_wrapper can work with only seconds. """
396 if timeout is not None:
397 if timeout <= 0:
398 timeout = 0
399 else:
400 # select.poll.poll() has a resolution of 1 millisecond,
401 # round away from zero to wait *at least* timeout seconds.
402 timeout = math.ceil(timeout * 1000)
403
404 result = self._poll.poll(timeout)
405 return result
406
407 def select(self, timeout=None):
408 ready = []
409 fd_events = _syscall_wrapper(self._wrap_poll, True, timeout=timeout)
410 for fd, event_mask in fd_events:
411 events = 0
412 if event_mask & ~select.POLLIN:
413 events |= EVENT_WRITE
414 if event_mask & ~select.POLLOUT:
415 events |= EVENT_READ
416
417 key = self._key_from_fd(fd)
418 if key:
419 ready.append((key, events & key.events))
420
421 return ready
422
423 __all__.append('PollSelector')
424
425 if hasattr(select, "epoll"):
426 class EpollSelector(BaseSelector):
427 """ Epoll-based selector """
428 def __init__(self):
429 super(EpollSelector, self).__init__()
430 self._epoll = select.epoll()
431
432 def fileno(self):
433 return self._epoll.fileno()
434
435 def register(self, fileobj, events, data=None):
436 key = super(EpollSelector, self).register(fileobj, events, data)
437 events_mask = 0
438 if events & EVENT_READ:
439 events_mask |= select.EPOLLIN
440 if events & EVENT_WRITE:
441 events_mask |= select.EPOLLOUT
442 _syscall_wrapper(self._epoll.register, False, key.fd, events_mask)
443 return key
444
445 def unregister(self, fileobj):
446 key = super(EpollSelector, self).unregister(fileobj)
447 try:
448 _syscall_wrapper(self._epoll.unregister, False, key.fd)
449 except _ERROR_TYPES:
450 # This can occur when the fd was closed since registry.
451 pass
452 return key
453
454 def select(self, timeout=None):
455 if timeout is not None:
456 if timeout <= 0:
457 timeout = 0.0
458 else:
459 # select.epoll.poll() has a resolution of 1 millisecond
460 # but luckily takes seconds so we don't need a wrapper
461 # like PollSelector. Just for better rounding.
462 timeout = math.ceil(timeout * 1000) * 0.001
463 timeout = float(timeout)
464 else:
465 timeout = -1.0 # epoll.poll() must have a float.
466
467 # We always want at least 1 to ensure that select can be called
468 # with no file descriptors registered. Otherwise will fail.
469 max_events = max(len(self._fd_to_key), 1)
470
471 ready = []
472 fd_events = _syscall_wrapper(self._epoll.poll, True,
473 timeout=timeout,
474 maxevents=max_events)
475 for fd, event_mask in fd_events:
476 events = 0
477 if event_mask & ~select.EPOLLIN:
478 events |= EVENT_WRITE
479 if event_mask & ~select.EPOLLOUT:
480 events |= EVENT_READ
481
482 key = self._key_from_fd(fd)
483 if key:
484 ready.append((key, events & key.events))
485 return ready
486
487 def close(self):
488 self._epoll.close()
489 super(EpollSelector, self).close()
490
491 __all__.append('EpollSelector')
492
493
494 if hasattr(select, "devpoll"):
495 class DevpollSelector(BaseSelector):
496 """Solaris /dev/poll selector."""
497
498 def __init__(self):
499 super(DevpollSelector, self).__init__()
500 self._devpoll = select.devpoll()
501
502 def fileno(self):
503 return self._devpoll.fileno()
504
505 def register(self, fileobj, events, data=None):
506 key = super(DevpollSelector, self).register(fileobj, events, data)
507 poll_events = 0
508 if events & EVENT_READ:
509 poll_events |= select.POLLIN
510 if events & EVENT_WRITE:
511 poll_events |= select.POLLOUT
512 self._devpoll.register(key.fd, poll_events)
513 return key
514
515 def unregister(self, fileobj):
516 key = super(DevpollSelector, self).unregister(fileobj)
517 self._devpoll.unregister(key.fd)
518 return key
519
520 def _wrap_poll(self, timeout=None):
521 """ Wrapper function for select.poll.poll() so that
522 _syscall_wrapper can work with only seconds. """
523 if timeout is not None:
524 if timeout <= 0:
525 timeout = 0
526 else:
527 # select.devpoll.poll() has a resolution of 1 millisecond,
528 # round away from zero to wait *at least* timeout seconds.
529 timeout = math.ceil(timeout * 1000)
530
531 result = self._devpoll.poll(timeout)
532 return result
533
534 def select(self, timeout=None):
535 ready = []
536 fd_events = _syscall_wrapper(self._wrap_poll, True, timeout=timeout)
537 for fd, event_mask in fd_events:
538 events = 0
539 if event_mask & ~select.POLLIN:
540 events |= EVENT_WRITE
541 if event_mask & ~select.POLLOUT:
542 events |= EVENT_READ
543
544 key = self._key_from_fd(fd)
545 if key:
546 ready.append((key, events & key.events))
547
548 return ready
549
550 def close(self):
551 self._devpoll.close()
552 super(DevpollSelector, self).close()
553
554 __all__.append('DevpollSelector')
555
556
557 if hasattr(select, "kqueue"):
558 class KqueueSelector(BaseSelector):
559 """ Kqueue / Kevent-based selector """
560 def __init__(self):
561 super(KqueueSelector, self).__init__()
562 self._kqueue = select.kqueue()
563
564 def fileno(self):
565 return self._kqueue.fileno()
566
567 def register(self, fileobj, events, data=None):
568 key = super(KqueueSelector, self).register(fileobj, events, data)
569 if events & EVENT_READ:
570 kevent = select.kevent(key.fd,
571 select.KQ_FILTER_READ,
572 select.KQ_EV_ADD)
573
574 _syscall_wrapper(self._kqueue.control, False, [kevent], 0, 0)
575
576 if events & EVENT_WRITE:
577 kevent = select.kevent(key.fd,
578 select.KQ_FILTER_WRITE,
579 select.KQ_EV_ADD)
580
581 _syscall_wrapper(self._kqueue.control, False, [kevent], 0, 0)
582
583 return key
584
585 def unregister(self, fileobj):
586 key = super(KqueueSelector, self).unregister(fileobj)
587 if key.events & EVENT_READ:
588 kevent = select.kevent(key.fd,
589 select.KQ_FILTER_READ,
590 select.KQ_EV_DELETE)
591 try:
592 _syscall_wrapper(self._kqueue.control, False, [kevent], 0, 0)
593 except _ERROR_TYPES:
594 pass
595 if key.events & EVENT_WRITE:
596 kevent = select.kevent(key.fd,
597 select.KQ_FILTER_WRITE,
598 select.KQ_EV_DELETE)
599 try:
600 _syscall_wrapper(self._kqueue.control, False, [kevent], 0, 0)
601 except _ERROR_TYPES:
602 pass
603
604 return key
605
606 def select(self, timeout=None):
607 if timeout is not None:
608 timeout = max(timeout, 0)
609
610 max_events = len(self._fd_to_key) * 2
611 ready_fds = {}
612
613 kevent_list = _syscall_wrapper(self._kqueue.control, True,
614 None, max_events, timeout)
615
616 for kevent in kevent_list:
617 fd = kevent.ident
618 event_mask = kevent.filter
619 events = 0
620 if event_mask == select.KQ_FILTER_READ:
621 events |= EVENT_READ
622 if event_mask == select.KQ_FILTER_WRITE:
623 events |= EVENT_WRITE
624
625 key = self._key_from_fd(fd)
626 if key:
627 if key.fd not in ready_fds:
628 ready_fds[key.fd] = (key, events & key.events)
629 else:
630 old_events = ready_fds[key.fd][1]
631 ready_fds[key.fd] = (key, (events | old_events) & key.events)
632
633 return list(ready_fds.values())
634
635 def close(self):
636 self._kqueue.close()
637 super(KqueueSelector, self).close()
638
639 __all__.append('KqueueSelector')
640
641
642 def _can_allocate(struct):
643 """ Checks that select structs can be allocated by the underlying
644 operating system, not just advertised by the select module. We don't
645 check select() because we'll be hopeful that most platforms that
646 don't have it available will not advertise it. (ie: GAE) """
647 try:
648 # select.poll() objects won't fail until used.
649 if struct == 'poll':
650 p = select.poll()
651 p.poll(0)
652
653 # All others will fail on allocation.
654 else:
655 getattr(select, struct)().close()
656 return True
657 except (OSError, AttributeError):
658 return False
659
660
661 # Python 3.5 uses a more direct route to wrap system calls to increase speed.
662 if sys.version_info >= (3, 5):
663 def _syscall_wrapper(func, _, *args, **kwargs):
664 """ This is the short-circuit version of the below logic
665 because in Python 3.5+ all selectors restart system calls. """
666 return func(*args, **kwargs)
667 else:
668 def _syscall_wrapper(func, recalc_timeout, *args, **kwargs):
669 """ Wrapper function for syscalls that could fail due to EINTR.
670 All functions should be retried if there is time left in the timeout
671 in accordance with PEP 475. """
672 timeout = kwargs.get("timeout", None)
673 if timeout is None:
674 expires = None
675 recalc_timeout = False
676 else:
677 timeout = float(timeout)
678 if timeout < 0.0: # Timeout less than 0 treated as no timeout.
679 expires = None
680 else:
681 expires = monotonic() + timeout
682
683 args = list(args)
684 if recalc_timeout and "timeout" not in kwargs:
685 raise ValueError(
686 "Timeout must be in args or kwargs to be recalculated")
687
688 result = _SYSCALL_SENTINEL
689 while result is _SYSCALL_SENTINEL:
690 try:
691 result = func(*args, **kwargs)
692 # OSError is thrown by select.select
693 # IOError is thrown by select.epoll.poll
694 # select.error is thrown by select.poll.poll
695 # Aren't we thankful for Python 3.x rework for exceptions?
696 except (OSError, IOError, select.error) as e:
697 # select.error wasn't a subclass of OSError in the past.
698 errcode = None
699 if hasattr(e, "errno"):
700 errcode = e.errno
701 elif hasattr(e, "args"):
702 errcode = e.args[0]
703
704 # Also test for the Windows equivalent of EINTR.
705 is_interrupt = (errcode == errno.EINTR or (hasattr(errno, "WSAEINTR") and
706 errcode == errno.WSAEINTR))
707
708 if is_interrupt:
709 if expires is not None:
710 current_time = monotonic()
711 if current_time > expires:
712 raise OSError(errno=errno.ETIMEDOUT)
713 if recalc_timeout:
714 if "timeout" in kwargs:
715 kwargs["timeout"] = expires - current_time
716 continue
717 raise
718 return result
719
720
721 # Choose the best implementation, roughly:
722 # kqueue == devpoll == epoll > poll > select
723 # select() also can't accept a FD > FD_SETSIZE (usually around 1024)
724 def DefaultSelector():
725 """ This function serves as a first call for DefaultSelector to
726 detect if the select module is being monkey-patched incorrectly
727 by eventlet, greenlet, and preserve proper behavior. """
728 global _DEFAULT_SELECTOR
729 if _DEFAULT_SELECTOR is None:
730 if platform.system() == 'Java': # Platform-specific: Jython
731 _DEFAULT_SELECTOR = JythonSelectSelector
732 elif _can_allocate('kqueue'):
733 _DEFAULT_SELECTOR = KqueueSelector
734 elif _can_allocate('devpoll'):
735 _DEFAULT_SELECTOR = DevpollSelector
736 elif _can_allocate('epoll'):
737 _DEFAULT_SELECTOR = EpollSelector
738 elif _can_allocate('poll'):
739 _DEFAULT_SELECTOR = PollSelector
740 elif hasattr(select, 'select'):
741 _DEFAULT_SELECTOR = SelectSelector
742 else: # Platform-specific: AppEngine
743 raise RuntimeError('Platform does not have a selector.')
744 return _DEFAULT_SELECTOR()