blob: bb15a1cb1bada1ae70ad4fb2a0863017215754a0 [file] [log] [blame]
Charles-François Natali243d8d82013-09-04 19:02:49 +02001"""Selectors module.
2
3This module allows high-level and efficient I/O multiplexing, built upon the
4`select` module primitives.
5"""
6
7
Victor Stinnerda492a82014-02-20 10:37:27 +01008from abc import ABCMeta, abstractmethod
Serhiy Storchaka2e576f52017-04-24 09:05:00 +03009from collections import namedtuple
10from collections.abc import Mapping
Victor Stinnerdcd97402014-01-31 12:12:53 +010011import math
Charles-François Natali243d8d82013-09-04 19:02:49 +020012import select
13import sys
14
15
16# generic events, that must be mapped to implementation-specific ones
17EVENT_READ = (1 << 0)
18EVENT_WRITE = (1 << 1)
19
20
21def _fileobj_to_fd(fileobj):
22 """Return a file descriptor from a file object.
23
24 Parameters:
25 fileobj -- file object or file descriptor
26
27 Returns:
28 corresponding file descriptor
Guido van Rossum9710ff02013-12-07 15:57:01 -080029
30 Raises:
31 ValueError if the object is invalid
Charles-François Natali243d8d82013-09-04 19:02:49 +020032 """
33 if isinstance(fileobj, int):
34 fd = fileobj
35 else:
36 try:
37 fd = int(fileobj.fileno())
38 except (AttributeError, TypeError, ValueError):
39 raise ValueError("Invalid file object: "
40 "{!r}".format(fileobj)) from None
41 if fd < 0:
42 raise ValueError("Invalid file descriptor: {}".format(fd))
43 return fd
44
45
46SelectorKey = namedtuple('SelectorKey', ['fileobj', 'fd', 'events', 'data'])
Charles-François Natali243d8d82013-09-04 19:02:49 +020047
Yury Selivanov0c6a3442016-03-02 10:37:59 -050048SelectorKey.__doc__ = """SelectorKey(fileobj, fd, events, data)
49
50 Object used to associate a file object to its backing
51 file descriptor, selected event mask, and attached data.
52"""
53if sys.version_info >= (3, 5):
54 SelectorKey.fileobj.__doc__ = 'File object registered.'
55 SelectorKey.fd.__doc__ = 'Underlying file descriptor.'
56 SelectorKey.events.__doc__ = 'Events that must be waited for on this file object.'
57 SelectorKey.data.__doc__ = ('''Optional opaque data associated to this file object.
58 For example, this could be used to store a per-client session ID.''')
Charles-François Natali243d8d82013-09-04 19:02:49 +020059
Abhijeet Kasurdebcd47832020-07-23 08:43:37 +053060
Charles-François Natali4574b492013-10-30 20:31:04 +010061class _SelectorMapping(Mapping):
62 """Mapping of file objects to selector keys."""
63
64 def __init__(self, selector):
65 self._selector = selector
66
67 def __len__(self):
68 return len(self._selector._fd_to_key)
69
70 def __getitem__(self, fileobj):
71 try:
Guido van Rossum9710ff02013-12-07 15:57:01 -080072 fd = self._selector._fileobj_lookup(fileobj)
73 return self._selector._fd_to_key[fd]
Charles-François Natali4574b492013-10-30 20:31:04 +010074 except KeyError:
75 raise KeyError("{!r} is not registered".format(fileobj)) from None
76
77 def __iter__(self):
78 return iter(self._selector._fd_to_key)
79
80
Charles-François Natali243d8d82013-09-04 19:02:49 +020081class BaseSelector(metaclass=ABCMeta):
Charles-François Natalib3330a0a2013-12-01 11:04:17 +010082 """Selector abstract base class.
Charles-François Natali243d8d82013-09-04 19:02:49 +020083
84 A selector supports registering file objects to be monitored for specific
85 I/O events.
86
87 A file object is a file descriptor or any object with a `fileno()` method.
88 An arbitrary object can be attached to the file object, which can be used
89 for example to store context information, a callback, etc.
90
91 A selector can use various implementations (select(), poll(), epoll()...)
92 depending on the platform. The default `Selector` class uses the most
Yury Selivanovb0b0e622014-02-18 22:27:48 -050093 efficient implementation on the current platform.
Charles-François Natali243d8d82013-09-04 19:02:49 +020094 """
95
Charles-François Natalib3330a0a2013-12-01 11:04:17 +010096 @abstractmethod
Charles-François Natali243d8d82013-09-04 19:02:49 +020097 def register(self, fileobj, events, data=None):
98 """Register a file object.
99
100 Parameters:
101 fileobj -- file object or file descriptor
102 events -- events to monitor (bitwise mask of EVENT_READ|EVENT_WRITE)
103 data -- attached data
104
105 Returns:
106 SelectorKey instance
Guido van Rossum9710ff02013-12-07 15:57:01 -0800107
108 Raises:
109 ValueError if events is invalid
110 KeyError if fileobj is already registered
111 OSError if fileobj is closed or otherwise is unacceptable to
112 the underlying system call (if a system call is made)
113
114 Note:
115 OSError may or may not be raised
Charles-François Natali243d8d82013-09-04 19:02:49 +0200116 """
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100117 raise NotImplementedError
Charles-François Natali243d8d82013-09-04 19:02:49 +0200118
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100119 @abstractmethod
Charles-François Natali243d8d82013-09-04 19:02:49 +0200120 def unregister(self, fileobj):
121 """Unregister a file object.
122
123 Parameters:
124 fileobj -- file object or file descriptor
125
126 Returns:
127 SelectorKey instance
Guido van Rossum9710ff02013-12-07 15:57:01 -0800128
129 Raises:
130 KeyError if fileobj is not registered
131
132 Note:
133 If fileobj is registered but has since been closed this does
134 *not* raise OSError (even if the wrapped syscall does)
Charles-François Natali243d8d82013-09-04 19:02:49 +0200135 """
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100136 raise NotImplementedError
Charles-François Natali243d8d82013-09-04 19:02:49 +0200137
138 def modify(self, fileobj, events, data=None):
139 """Change a registered file object monitored events or attached data.
140
141 Parameters:
142 fileobj -- file object or file descriptor
143 events -- events to monitor (bitwise mask of EVENT_READ|EVENT_WRITE)
144 data -- attached data
145
146 Returns:
147 SelectorKey instance
Guido van Rossum9710ff02013-12-07 15:57:01 -0800148
149 Raises:
150 Anything that unregister() or register() raises
Charles-François Natali243d8d82013-09-04 19:02:49 +0200151 """
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100152 self.unregister(fileobj)
153 return self.register(fileobj, events, data)
Charles-François Natali243d8d82013-09-04 19:02:49 +0200154
155 @abstractmethod
156 def select(self, timeout=None):
157 """Perform the actual selection, until some monitored file objects are
158 ready or a timeout expires.
159
160 Parameters:
161 timeout -- if timeout > 0, this specifies the maximum wait time, in
162 seconds
163 if timeout <= 0, the select() call won't block, and will
164 report the currently ready file objects
165 if timeout is None, select() will block until a monitored
166 file object becomes ready
167
168 Returns:
169 list of (key, events) for ready file objects
170 `events` is a bitwise mask of EVENT_READ|EVENT_WRITE
171 """
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100172 raise NotImplementedError
Charles-François Natali243d8d82013-09-04 19:02:49 +0200173
174 def close(self):
175 """Close the selector.
176
177 This must be called to make sure that any underlying resource is freed.
178 """
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100179 pass
Charles-François Natali243d8d82013-09-04 19:02:49 +0200180
181 def get_key(self, fileobj):
182 """Return the key associated to a registered file object.
183
184 Returns:
185 SelectorKey for this file object
186 """
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100187 mapping = self.get_map()
Victor Stinner458fc6f2015-01-13 10:00:55 +0100188 if mapping is None:
189 raise RuntimeError('Selector is closed')
Charles-François Natali243d8d82013-09-04 19:02:49 +0200190 try:
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100191 return mapping[fileobj]
Charles-François Natali243d8d82013-09-04 19:02:49 +0200192 except KeyError:
193 raise KeyError("{!r} is not registered".format(fileobj)) from None
194
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100195 @abstractmethod
Charles-François Natali4574b492013-10-30 20:31:04 +0100196 def get_map(self):
197 """Return a mapping of file objects to selector keys."""
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100198 raise NotImplementedError
Charles-François Natali4574b492013-10-30 20:31:04 +0100199
Charles-François Natali243d8d82013-09-04 19:02:49 +0200200 def __enter__(self):
201 return self
202
203 def __exit__(self, *args):
204 self.close()
205
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100206
207class _BaseSelectorImpl(BaseSelector):
208 """Base selector implementation."""
209
210 def __init__(self):
211 # this maps file descriptors to keys
212 self._fd_to_key = {}
213 # read-only mapping returned by get_map()
214 self._map = _SelectorMapping(self)
215
Guido van Rossum9710ff02013-12-07 15:57:01 -0800216 def _fileobj_lookup(self, fileobj):
217 """Return a file descriptor from a file object.
218
219 This wraps _fileobj_to_fd() to do an exhaustive search in case
220 the object is invalid but we still have it in our map. This
221 is used by unregister() so we can unregister an object that
222 was previously registered even if it is closed. It is also
223 used by _SelectorMapping.
224 """
225 try:
226 return _fileobj_to_fd(fileobj)
227 except ValueError:
228 # Do an exhaustive search.
229 for key in self._fd_to_key.values():
230 if key.fileobj is fileobj:
231 return key.fd
232 # Raise ValueError after all.
233 raise
234
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100235 def register(self, fileobj, events, data=None):
236 if (not events) or (events & ~(EVENT_READ | EVENT_WRITE)):
237 raise ValueError("Invalid events: {!r}".format(events))
238
Guido van Rossum9710ff02013-12-07 15:57:01 -0800239 key = SelectorKey(fileobj, self._fileobj_lookup(fileobj), events, data)
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100240
241 if key.fd in self._fd_to_key:
Guido van Rossum9710ff02013-12-07 15:57:01 -0800242 raise KeyError("{!r} (FD {}) is already registered"
243 .format(fileobj, key.fd))
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100244
245 self._fd_to_key[key.fd] = key
246 return key
247
248 def unregister(self, fileobj):
249 try:
Guido van Rossum9710ff02013-12-07 15:57:01 -0800250 key = self._fd_to_key.pop(self._fileobj_lookup(fileobj))
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100251 except KeyError:
252 raise KeyError("{!r} is not registered".format(fileobj)) from None
253 return key
254
255 def modify(self, fileobj, events, data=None):
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100256 try:
Guido van Rossum9710ff02013-12-07 15:57:01 -0800257 key = self._fd_to_key[self._fileobj_lookup(fileobj)]
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100258 except KeyError:
259 raise KeyError("{!r} is not registered".format(fileobj)) from None
260 if events != key.events:
261 self.unregister(fileobj)
262 key = self.register(fileobj, events, data)
263 elif data != key.data:
264 # Use a shortcut to update the data.
265 key = key._replace(data=data)
266 self._fd_to_key[key.fd] = key
267 return key
268
269 def close(self):
270 self._fd_to_key.clear()
Victor Stinner38dc2502015-01-13 09:58:33 +0100271 self._map = None
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100272
273 def get_map(self):
274 return self._map
275
Charles-François Natali243d8d82013-09-04 19:02:49 +0200276 def _key_from_fd(self, fd):
277 """Return the key associated to a given file descriptor.
278
279 Parameters:
280 fd -- file descriptor
281
282 Returns:
283 corresponding key, or None if not found
284 """
285 try:
286 return self._fd_to_key[fd]
287 except KeyError:
288 return None
289
290
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100291class SelectSelector(_BaseSelectorImpl):
Charles-François Natali243d8d82013-09-04 19:02:49 +0200292 """Select-based selector."""
293
294 def __init__(self):
295 super().__init__()
296 self._readers = set()
297 self._writers = set()
298
299 def register(self, fileobj, events, data=None):
300 key = super().register(fileobj, events, data)
301 if events & EVENT_READ:
302 self._readers.add(key.fd)
303 if events & EVENT_WRITE:
304 self._writers.add(key.fd)
305 return key
306
307 def unregister(self, fileobj):
308 key = super().unregister(fileobj)
309 self._readers.discard(key.fd)
310 self._writers.discard(key.fd)
311 return key
312
313 if sys.platform == 'win32':
314 def _select(self, r, w, _, timeout=None):
315 r, w, x = select.select(r, w, w, timeout)
316 return r, w + x, []
317 else:
318 _select = select.select
319
320 def select(self, timeout=None):
321 timeout = None if timeout is None else max(timeout, 0)
322 ready = []
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400323 try:
324 r, w, _ = self._select(self._readers, self._writers, [], timeout)
325 except InterruptedError:
326 return ready
Charles-François Natali243d8d82013-09-04 19:02:49 +0200327 r = set(r)
328 w = set(w)
329 for fd in r | w:
330 events = 0
331 if fd in r:
332 events |= EVENT_READ
333 if fd in w:
334 events |= EVENT_WRITE
335
336 key = self._key_from_fd(fd)
337 if key:
338 ready.append((key, events & key.events))
339 return ready
340
341
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200342class _PollLikeSelector(_BaseSelectorImpl):
343 """Base class shared between poll, epoll and devpoll selectors."""
344 _selector_cls = None
Giampaolo Rodolafbfaa6f2017-06-09 22:20:41 +0200345 _EVENT_READ = None
346 _EVENT_WRITE = None
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200347
348 def __init__(self):
349 super().__init__()
350 self._selector = self._selector_cls()
351
352 def register(self, fileobj, events, data=None):
353 key = super().register(fileobj, events, data)
354 poller_events = 0
355 if events & EVENT_READ:
356 poller_events |= self._EVENT_READ
357 if events & EVENT_WRITE:
358 poller_events |= self._EVENT_WRITE
359 try:
360 self._selector.register(key.fd, poller_events)
Giampaolo Rodolaced36a92017-06-12 14:43:40 +0200361 except:
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200362 super().unregister(fileobj)
363 raise
364 return key
365
366 def unregister(self, fileobj):
367 key = super().unregister(fileobj)
368 try:
369 self._selector.unregister(key.fd)
370 except OSError:
371 # This can happen if the FD was closed since it
372 # was registered.
373 pass
374 return key
375
Giampaolo Rodolafbfaa6f2017-06-09 22:20:41 +0200376 def modify(self, fileobj, events, data=None):
377 try:
378 key = self._fd_to_key[self._fileobj_lookup(fileobj)]
379 except KeyError:
380 raise KeyError(f"{fileobj!r} is not registered") from None
381
382 changed = False
383 if events != key.events:
384 selector_events = 0
385 if events & EVENT_READ:
386 selector_events |= self._EVENT_READ
387 if events & EVENT_WRITE:
388 selector_events |= self._EVENT_WRITE
389 try:
390 self._selector.modify(key.fd, selector_events)
Giampaolo Rodola05dc20f2017-06-11 01:51:52 +0200391 except:
Giampaolo Rodolafbfaa6f2017-06-09 22:20:41 +0200392 super().unregister(fileobj)
393 raise
394 changed = True
395 if data != key.data:
396 changed = True
397
398 if changed:
399 key = key._replace(events=events, data=data)
400 self._fd_to_key[key.fd] = key
401 return key
402
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200403 def select(self, timeout=None):
404 # This is shared between poll() and epoll().
405 # epoll() has a different signature and handling of timeout parameter.
406 if timeout is None:
407 timeout = None
408 elif timeout <= 0:
409 timeout = 0
410 else:
411 # poll() has a resolution of 1 millisecond, round away from
412 # zero to wait *at least* timeout seconds.
413 timeout = math.ceil(timeout * 1e3)
414 ready = []
415 try:
416 fd_event_list = self._selector.poll(timeout)
417 except InterruptedError:
418 return ready
419 for fd, event in fd_event_list:
420 events = 0
421 if event & ~self._EVENT_READ:
422 events |= EVENT_WRITE
423 if event & ~self._EVENT_WRITE:
424 events |= EVENT_READ
425
426 key = self._key_from_fd(fd)
427 if key:
428 ready.append((key, events & key.events))
429 return ready
430
431
Charles-François Natali243d8d82013-09-04 19:02:49 +0200432if hasattr(select, 'poll'):
433
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200434 class PollSelector(_PollLikeSelector):
Charles-François Natali243d8d82013-09-04 19:02:49 +0200435 """Poll-based selector."""
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200436 _selector_cls = select.poll
437 _EVENT_READ = select.POLLIN
438 _EVENT_WRITE = select.POLLOUT
Charles-François Natali243d8d82013-09-04 19:02:49 +0200439
440
441if hasattr(select, 'epoll'):
442
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200443 class EpollSelector(_PollLikeSelector):
Charles-François Natali243d8d82013-09-04 19:02:49 +0200444 """Epoll-based selector."""
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200445 _selector_cls = select.epoll
446 _EVENT_READ = select.EPOLLIN
447 _EVENT_WRITE = select.EPOLLOUT
Charles-François Natali243d8d82013-09-04 19:02:49 +0200448
449 def fileno(self):
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200450 return self._selector.fileno()
Charles-François Natali243d8d82013-09-04 19:02:49 +0200451
452 def select(self, timeout=None):
Victor Stinner567b26e2014-01-21 21:00:47 +0100453 if timeout is None:
454 timeout = -1
455 elif timeout <= 0:
456 timeout = 0
Victor Stinnerdcd97402014-01-31 12:12:53 +0100457 else:
458 # epoll_wait() has a resolution of 1 millisecond, round away
459 # from zero to wait *at least* timeout seconds.
460 timeout = math.ceil(timeout * 1e3) * 1e-3
Yury Selivanovd60ef4a2014-12-08 12:21:58 -0500461
Yury Selivanovdfc44e02014-12-08 12:30:10 -0500462 # epoll_wait() expects `maxevents` to be greater than zero;
Yury Selivanovd60ef4a2014-12-08 12:21:58 -0500463 # we want to make sure that `select()` can be called when no
464 # FD is registered.
465 max_ev = max(len(self._fd_to_key), 1)
466
Charles-François Natali243d8d82013-09-04 19:02:49 +0200467 ready = []
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400468 try:
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200469 fd_event_list = self._selector.poll(timeout, max_ev)
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400470 except InterruptedError:
471 return ready
Charles-François Natali243d8d82013-09-04 19:02:49 +0200472 for fd, event in fd_event_list:
473 events = 0
474 if event & ~select.EPOLLIN:
475 events |= EVENT_WRITE
476 if event & ~select.EPOLLOUT:
477 events |= EVENT_READ
478
479 key = self._key_from_fd(fd)
480 if key:
481 ready.append((key, events & key.events))
482 return ready
483
484 def close(self):
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200485 self._selector.close()
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400486 super().close()
Charles-François Natali243d8d82013-09-04 19:02:49 +0200487
488
Giampaolo Rodola'f97e8292014-03-20 21:43:41 +0100489if hasattr(select, 'devpoll'):
490
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200491 class DevpollSelector(_PollLikeSelector):
Giampaolo Rodola'f97e8292014-03-20 21:43:41 +0100492 """Solaris /dev/poll selector."""
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200493 _selector_cls = select.devpoll
494 _EVENT_READ = select.POLLIN
495 _EVENT_WRITE = select.POLLOUT
Giampaolo Rodola'f97e8292014-03-20 21:43:41 +0100496
497 def fileno(self):
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200498 return self._selector.fileno()
Giampaolo Rodola'f97e8292014-03-20 21:43:41 +0100499
500 def close(self):
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200501 self._selector.close()
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400502 super().close()
Giampaolo Rodola'f97e8292014-03-20 21:43:41 +0100503
504
Charles-François Natali243d8d82013-09-04 19:02:49 +0200505if hasattr(select, 'kqueue'):
506
Charles-François Natalib3330a0a2013-12-01 11:04:17 +0100507 class KqueueSelector(_BaseSelectorImpl):
Charles-François Natali243d8d82013-09-04 19:02:49 +0200508 """Kqueue-based selector."""
509
510 def __init__(self):
511 super().__init__()
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200512 self._selector = select.kqueue()
Charles-François Natali243d8d82013-09-04 19:02:49 +0200513
514 def fileno(self):
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200515 return self._selector.fileno()
Charles-François Natali243d8d82013-09-04 19:02:49 +0200516
517 def register(self, fileobj, events, data=None):
518 key = super().register(fileobj, events, data)
Yury Selivanov525aedc2016-09-15 19:30:42 -0400519 try:
520 if events & EVENT_READ:
521 kev = select.kevent(key.fd, select.KQ_FILTER_READ,
522 select.KQ_EV_ADD)
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200523 self._selector.control([kev], 0, 0)
Yury Selivanov525aedc2016-09-15 19:30:42 -0400524 if events & EVENT_WRITE:
525 kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
526 select.KQ_EV_ADD)
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200527 self._selector.control([kev], 0, 0)
Giampaolo Rodola05dc20f2017-06-11 01:51:52 +0200528 except:
Yury Selivanov525aedc2016-09-15 19:30:42 -0400529 super().unregister(fileobj)
530 raise
Charles-François Natali243d8d82013-09-04 19:02:49 +0200531 return key
532
533 def unregister(self, fileobj):
534 key = super().unregister(fileobj)
535 if key.events & EVENT_READ:
536 kev = select.kevent(key.fd, select.KQ_FILTER_READ,
537 select.KQ_EV_DELETE)
Guido van Rossum9710ff02013-12-07 15:57:01 -0800538 try:
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200539 self._selector.control([kev], 0, 0)
Guido van Rossum9710ff02013-12-07 15:57:01 -0800540 except OSError:
541 # This can happen if the FD was closed since it
542 # was registered.
543 pass
Charles-François Natali243d8d82013-09-04 19:02:49 +0200544 if key.events & EVENT_WRITE:
545 kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
546 select.KQ_EV_DELETE)
Guido van Rossum9710ff02013-12-07 15:57:01 -0800547 try:
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200548 self._selector.control([kev], 0, 0)
Guido van Rossum9710ff02013-12-07 15:57:01 -0800549 except OSError:
550 # See comment above.
551 pass
Charles-François Natali243d8d82013-09-04 19:02:49 +0200552 return key
553
554 def select(self, timeout=None):
555 timeout = None if timeout is None else max(timeout, 0)
Russell Davisba1bcff2020-04-15 11:57:06 -0700556 # If max_ev is 0, kqueue will ignore the timeout. For consistent
557 # behavior with the other selector classes, we prevent that here
558 # (using max). See https://bugs.python.org/issue29255
559 max_ev = max(len(self._fd_to_key), 1)
Charles-François Natali243d8d82013-09-04 19:02:49 +0200560 ready = []
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400561 try:
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200562 kev_list = self._selector.control(None, max_ev, timeout)
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400563 except InterruptedError:
564 return ready
Charles-François Natali243d8d82013-09-04 19:02:49 +0200565 for kev in kev_list:
566 fd = kev.ident
567 flag = kev.filter
568 events = 0
569 if flag == select.KQ_FILTER_READ:
570 events |= EVENT_READ
571 if flag == select.KQ_FILTER_WRITE:
572 events |= EVENT_WRITE
573
574 key = self._key_from_fd(fd)
575 if key:
576 ready.append((key, events & key.events))
577 return ready
578
579 def close(self):
Giampaolo Rodola62c7d902017-05-20 11:34:44 +0200580 self._selector.close()
Yury Selivanov90ecfe62015-05-11 13:48:16 -0400581 super().close()
Charles-François Natali243d8d82013-09-04 19:02:49 +0200582
583
Abhijeet Kasurdebcd47832020-07-23 08:43:37 +0530584def _can_use(method):
585 """Check if we can use the selector depending upon the
586 operating system. """
587 # Implementation based upon https://github.com/sethmlarson/selectors2/blob/master/selectors2.py
588 selector = getattr(select, method, None)
589 if selector is None:
590 # select module does not implement method
591 return False
592 # check if the OS and Kernel actually support the method. Call may fail with
593 # OSError: [Errno 38] Function not implemented
594 try:
595 selector_obj = selector()
596 if method == 'poll':
597 # check that poll actually works
598 selector_obj.poll(0)
599 else:
600 # close epoll, kqueue, and devpoll fd
601 selector_obj.close()
602 return True
603 except OSError:
604 return False
605
606
Victor Stinner53a6d742015-01-09 00:13:39 +0100607# Choose the best implementation, roughly:
608# epoll|kqueue|devpoll > poll > select.
Charles-François Natali243d8d82013-09-04 19:02:49 +0200609# select() also can't accept a FD > FD_SETSIZE (usually around 1024)
Abhijeet Kasurdebcd47832020-07-23 08:43:37 +0530610if _can_use('kqueue'):
Charles-François Natali243d8d82013-09-04 19:02:49 +0200611 DefaultSelector = KqueueSelector
Abhijeet Kasurdebcd47832020-07-23 08:43:37 +0530612elif _can_use('epoll'):
Charles-François Natali243d8d82013-09-04 19:02:49 +0200613 DefaultSelector = EpollSelector
Abhijeet Kasurdebcd47832020-07-23 08:43:37 +0530614elif _can_use('devpoll'):
Giampaolo Rodola'f97e8292014-03-20 21:43:41 +0100615 DefaultSelector = DevpollSelector
Abhijeet Kasurdebcd47832020-07-23 08:43:37 +0530616elif _can_use('poll'):
Charles-François Natali243d8d82013-09-04 19:02:49 +0200617 DefaultSelector = PollSelector
618else:
619 DefaultSelector = SelectSelector