1
"""Event loop using a selector and related classes.
3
A selector is a "notify-when-ready" multiplexer. For a subclass which
4
also includes support for signal handling, see the unix_events sub-module.
7
__all__ = 'BaseSelectorEventLoop',
20
except ImportError: # pragma: no cover
23
from . import base_events
24
from . import constants
27
from . import protocols
28
from . import sslproto
29
from . import transports
31
from .log import logger
33
_HAS_SENDMSG = hasattr(socket.socket, 'sendmsg')
37
SC_IOV_MAX = os.sysconf('SC_IOV_MAX')
42
def _test_selector_event(selector, fd, event):
43
# Test if the selector is monitoring 'event' events
44
# for the file descriptor 'fd'.
46
key = selector.get_key(fd)
50
return bool(key.events & event)
53
class BaseSelectorEventLoop(base_events.BaseEventLoop):
54
"""Selector event loop.
56
See events.EventLoop for API specification.
59
def __init__(self, selector=None):
63
selector = selectors.DefaultSelector()
64
logger.debug('Using selector: %s', selector.__class__.__name__)
65
self._selector = selector
66
self._make_self_pipe()
67
self._transports = weakref.WeakValueDictionary()
69
def _make_socket_transport(self, sock, protocol, waiter=None, *,
70
extra=None, server=None, context=None):
71
self._ensure_fd_no_transport(sock)
72
4
5
return _SelectorSocketTransport(self, sock, protocol, waiter,
73
extra, server, context=context)
75
def _make_ssl_transport(
76
self, rawsock, protocol, sslcontext, waiter=None,
77
*, server_side=False, server_hostname=None,
78
extra=None, server=None,
79
ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT,
80
ssl_shutdown_timeout=constants.SSL_SHUTDOWN_TIMEOUT,
83
self._ensure_fd_no_transport(rawsock)
84
ssl_protocol = sslproto.SSLProtocol(
85
self, protocol, sslcontext, waiter,
86
server_side, server_hostname,
87
ssl_handshake_timeout=ssl_handshake_timeout,
88
ssl_shutdown_timeout=ssl_shutdown_timeout,
90
_SelectorSocketTransport(self, rawsock, ssl_protocol,
91
extra=extra, server=server, context=context)
92
return ssl_protocol._app_transport
94
def _make_datagram_transport(self, sock, protocol,
95
address=None, waiter=None, extra=None):
96
self._ensure_fd_no_transport(sock)
97
return _SelectorDatagramTransport(self, sock, protocol,
98
address, waiter, extra)
101
if self.is_running():
102
raise RuntimeError("Cannot close a running event loop")
105
self._close_self_pipe()
107
if self._selector is not None:
108
self._selector.close()
109
self._selector = None
111
def _close_self_pipe(self):
112
self._remove_reader(self._ssock.fileno())
117
self._internal_fds -= 1
119
def _make_self_pipe(self):
120
# A self-socket, really. :-)
121
self._ssock, self._csock = socket.socketpair()
122
self._ssock.setblocking(False)
123
self._csock.setblocking(False)
124
self._internal_fds += 1
125
self._add_reader(self._ssock.fileno(), self._read_from_self)
127
def _process_self_data(self, data):
130
def _read_from_self(self):
133
1
1
data = self._ssock.recv(4096)
136
self._process_self_data(data)
137
except InterruptedError:
139
except BlockingIOError:
142
def _write_to_self(self):
143
# This may be called from a different thread, possibly after
144
# _close_self_pipe() has been called or even while it is
145
# running. Guard for self._csock being None or closed. When
146
# a socket is closed, send() raises OSError (with errno set to
147
# EBADF, but let's not rely on the exact error code).
156
logger.debug("Fail to write a null byte into the "
160
def _start_serving(self, protocol_factory, sock,
161
sslcontext=None, server=None, backlog=100,
162
ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT,
163
ssl_shutdown_timeout=constants.SSL_SHUTDOWN_TIMEOUT, context=None):
164
self._add_reader(sock.fileno(), self._accept_connection,
165
protocol_factory, sock, sslcontext, server, backlog,
166
ssl_handshake_timeout, ssl_shutdown_timeout, context)
168
def _accept_connection(
169
self, protocol_factory, sock,
170
sslcontext=None, server=None, backlog=100,
171
ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT,
172
ssl_shutdown_timeout=constants.SSL_SHUTDOWN_TIMEOUT, context=None):
173
# This method is only called once for each event loop tick where the
174
# listening socket has triggered an EVENT_READ. There may be multiple
175
# connections waiting for an .accept() so it is called in a loop.
176
# See https://bugs.python.org/issue27906 for more details.
177
for _ in range(backlog + 1):
179
3
21
conn, addr = sock.accept()
181
logger.debug("%r got a new connection from %r: %r",
183
conn.setblocking(False)
184
except ConnectionAbortedError:
185
# Discard connections that were aborted before accept().
187
except (BlockingIOError, InterruptedError):
188
# Early exit because of a signal or
189
# the socket accept buffer is empty.
191
except OSError as exc:
192
# There's nowhere to send the error, so just log it.
193
if exc.errno in (errno.EMFILE, errno.ENFILE,
194
errno.ENOBUFS, errno.ENOMEM):
195
# Some platforms (e.g. Linux keep reporting the FD as
196
# ready, so we remove the read handler temporarily.
197
# We'll try again in a while.
198
self.call_exception_handler({
199
'message': 'socket.accept() out of system resource',
201
'socket': trsock.TransportSocket(sock),
203
self._remove_reader(sock.fileno())
204
self.call_later(constants.ACCEPT_RETRY_DELAY,
206
protocol_factory, sock, sslcontext, server,
207
backlog, ssl_handshake_timeout,
208
ssl_shutdown_timeout, context)
210
raise # The event loop will catch, log and ignore it.
212
extra = {'peername': addr}
213
conn_context = context.copy() if context is not None else None
214
accept = self._accept_connection2(
215
protocol_factory, conn, extra, sslcontext, server,
216
ssl_handshake_timeout, ssl_shutdown_timeout, context=conn_context)
217
1
self.create_task(accept, context=conn_context)
219
async def _accept_connection2(
220
self, protocol_factory, conn, extra,
221
sslcontext=None, server=None,
222
ssl_handshake_timeout=constants.SSL_HANDSHAKE_TIMEOUT,
223
ssl_shutdown_timeout=constants.SSL_SHUTDOWN_TIMEOUT, context=None):
227
protocol = protocol_factory()
228
waiter = self.create_future()
230
transport = self._make_ssl_transport(
231
conn, protocol, sslcontext, waiter=waiter,
232
server_side=True, extra=extra, server=server,
233
ssl_handshake_timeout=ssl_handshake_timeout,
234
ssl_shutdown_timeout=ssl_shutdown_timeout,
237
1
9
transport = self._make_socket_transport(
238
conn, protocol, waiter=waiter, extra=extra,
239
server=server, context=context)
243
except BaseException:
245
# gh-109534: When an exception is raised by the SSLProtocol object the
246
# exception set in this future can keep the protocol object alive and
247
# cause a reference cycle.
250
# It's now up to the protocol to handle the connection.
252
except (SystemExit, KeyboardInterrupt):
254
except BaseException as exc:
258
'Error on transport creation for incoming connection',
261
if protocol is not None:
262
context['protocol'] = protocol
263
if transport is not None:
264
context['transport'] = transport
265
self.call_exception_handler(context)
267
def _ensure_fd_no_transport(self, fd):
269
if not isinstance(fileno, int):
271
fileno = int(fileno.fileno())
272
except (AttributeError, TypeError, ValueError):
273
# This code matches selectors._fileobj_to_fd function.
274
raise ValueError(f"Invalid file object: {fd!r}") from None
275
transport = self._transports.get(fileno)
276
if transport and not transport.is_closing():
278
f'File descriptor {fd!r} is used by transport '
281
def _add_reader(self, fd, callback, *args, context=None):
283
handle = events.Handle(callback, args, self, context=context)
284
key = self._selector.get_map().get(fd)
286
self._selector.register(fd, selectors.EVENT_READ,
289
mask, (reader, writer) = key.events, key.data
290
self._selector.modify(fd, mask | selectors.EVENT_READ,
292
if reader is not None:
296
def _remove_reader(self, fd):
299
key = self._selector.get_map().get(fd)
302
mask, (reader, writer) = key.events, key.data
303
mask &= ~selectors.EVENT_READ
305
self._selector.unregister(fd)
307
self._selector.modify(fd, mask, (None, writer))
309
if reader is not None:
315
def _add_writer(self, fd, callback, *args, context=None):
317
handle = events.Handle(callback, args, self, context=context)
318
key = self._selector.get_map().get(fd)
320
self._selector.register(fd, selectors.EVENT_WRITE,
323
mask, (reader, writer) = key.events, key.data
324
self._selector.modify(fd, mask | selectors.EVENT_WRITE,
326
if writer is not None:
330
def _remove_writer(self, fd):
331
"""Remove a writer callback."""
334
key = self._selector.get_map().get(fd)
337
mask, (reader, writer) = key.events, key.data
338
# Remove both writer and connector.
339
mask &= ~selectors.EVENT_WRITE
341
self._selector.unregister(fd)
343
self._selector.modify(fd, mask, (reader, None))
345
if writer is not None:
351
def add_reader(self, fd, callback, *args):
352
"""Add a reader callback."""
353
self._ensure_fd_no_transport(fd)
354
self._add_reader(fd, callback, *args)
356
def remove_reader(self, fd):
357
"""Remove a reader callback."""
358
self._ensure_fd_no_transport(fd)
359
return self._remove_reader(fd)
361
def add_writer(self, fd, callback, *args):
362
"""Add a writer callback.."""
363
self._ensure_fd_no_transport(fd)
364
self._add_writer(fd, callback, *args)
366
def remove_writer(self, fd):
367
"""Remove a writer callback."""
368
self._ensure_fd_no_transport(fd)
369
return self._remove_writer(fd)
371
async def sock_recv(self, sock, n):
372
"""Receive data from the socket.
374
The return value is a bytes object representing the data received.
375
The maximum amount of data to be received at once is specified by
378
base_events._check_ssl_socket(sock)
379
if self._debug and sock.gettimeout() != 0:
380
raise ValueError("the socket must be non-blocking")
383
except (BlockingIOError, InterruptedError):
385
fut = self.create_future()
387
self._ensure_fd_no_transport(fd)
388
handle = self._add_reader(fd, self._sock_recv, fut, sock, n)
389
fut.add_done_callback(
390
functools.partial(self._sock_read_done, fd, handle=handle))
393
def _sock_read_done(self, fd, fut, handle=None):
394
if handle is None or not handle.cancelled():
395
self.remove_reader(fd)
397
def _sock_recv(self, fut, sock, n):
398
# _sock_recv() can add itself as an I/O callback if the operation can't
399
# be done immediately. Don't use it directly, call sock_recv().
404
except (BlockingIOError, InterruptedError):
405
return # try again next time
406
except (SystemExit, KeyboardInterrupt):
408
except BaseException as exc:
409
fut.set_exception(exc)
413
async def sock_recv_into(self, sock, buf):
414
"""Receive data from the socket.
416
The received data is written into *buf* (a writable buffer).
417
The return value is the number of bytes written.
419
base_events._check_ssl_socket(sock)
420
if self._debug and sock.gettimeout() != 0:
421
raise ValueError("the socket must be non-blocking")
423
return sock.recv_into(buf)
424
except (BlockingIOError, InterruptedError):
426
fut = self.create_future()
428
self._ensure_fd_no_transport(fd)
429
handle = self._add_reader(fd, self._sock_recv_into, fut, sock, buf)
430
fut.add_done_callback(
431
functools.partial(self._sock_read_done, fd, handle=handle))
434
def _sock_recv_into(self, fut, sock, buf):
435
# _sock_recv_into() can add itself as an I/O callback if the operation
436
# can't be done immediately. Don't use it directly, call
441
nbytes = sock.recv_into(buf)
442
except (BlockingIOError, InterruptedError):
443
return # try again next time
444
except (SystemExit, KeyboardInterrupt):
446
except BaseException as exc:
447
fut.set_exception(exc)
449
fut.set_result(nbytes)
451
async def sock_recvfrom(self, sock, bufsize):
452
"""Receive a datagram from a datagram socket.
454
The return value is a tuple of (bytes, address) representing the
455
datagram received and the address it came from.
456
The maximum amount of data to be received at once is specified by
459
base_events._check_ssl_socket(sock)
460
if self._debug and sock.gettimeout() != 0:
461
raise ValueError("the socket must be non-blocking")
463
return sock.recvfrom(bufsize)
464
except (BlockingIOError, InterruptedError):
466
fut = self.create_future()
468
self._ensure_fd_no_transport(fd)
469
handle = self._add_reader(fd, self._sock_recvfrom, fut, sock, bufsize)
470
fut.add_done_callback(
471
functools.partial(self._sock_read_done, fd, handle=handle))
474
def _sock_recvfrom(self, fut, sock, bufsize):
475
# _sock_recvfrom() can add itself as an I/O callback if the operation
476
# can't be done immediately. Don't use it directly, call
481
result = sock.recvfrom(bufsize)
482
except (BlockingIOError, InterruptedError):
483
return # try again next time
484
except (SystemExit, KeyboardInterrupt):
486
except BaseException as exc:
487
fut.set_exception(exc)
489
fut.set_result(result)
491
async def sock_recvfrom_into(self, sock, buf, nbytes=0):
492
"""Receive data from the socket.
494
The received data is written into *buf* (a writable buffer).
495
The return value is a tuple of (number of bytes written, address).
497
base_events._check_ssl_socket(sock)
498
if self._debug and sock.gettimeout() != 0:
499
raise ValueError("the socket must be non-blocking")
504
return sock.recvfrom_into(buf, nbytes)
505
except (BlockingIOError, InterruptedError):
507
fut = self.create_future()
509
self._ensure_fd_no_transport(fd)
510
handle = self._add_reader(fd, self._sock_recvfrom_into, fut, sock, buf,
512
fut.add_done_callback(
513
functools.partial(self._sock_read_done, fd, handle=handle))
516
def _sock_recvfrom_into(self, fut, sock, buf, bufsize):
517
# _sock_recv_into() can add itself as an I/O callback if the operation
518
# can't be done immediately. Don't use it directly, call
523
result = sock.recvfrom_into(buf, bufsize)
524
except (BlockingIOError, InterruptedError):
525
return # try again next time
526
except (SystemExit, KeyboardInterrupt):
528
except BaseException as exc:
529
fut.set_exception(exc)
531
fut.set_result(result)
533
async def sock_sendall(self, sock, data):
534
"""Send data to the socket.
536
The socket must be connected to a remote socket. This method
537
continues to send data from data until either all data has been
538
sent or an error occurs. None is returned on success. On error,
539
an exception is raised, and there is no way to determine how much
540
data, if any, was successfully processed by the receiving end of
543
base_events._check_ssl_socket(sock)
544
if self._debug and sock.gettimeout() != 0:
545
raise ValueError("the socket must be non-blocking")
548
except (BlockingIOError, InterruptedError):
555
fut = self.create_future()
557
self._ensure_fd_no_transport(fd)
558
# use a trick with a list in closure to store a mutable state
559
handle = self._add_writer(fd, self._sock_sendall, fut, sock,
560
memoryview(data), [n])
561
fut.add_done_callback(
562
functools.partial(self._sock_write_done, fd, handle=handle))
565
def _sock_sendall(self, fut, sock, view, pos):
567
# Future cancellation can be scheduled on previous loop iteration
571
n = sock.send(view[start:])
572
except (BlockingIOError, InterruptedError):
574
except (SystemExit, KeyboardInterrupt):
576
except BaseException as exc:
577
fut.set_exception(exc)
582
if start == len(view):
587
async def sock_sendto(self, sock, data, address):
588
"""Send a datagram from sock to address.
590
The socket does not have to be connected. This method sends the
591
whole datagram in a single call. Return the number of bytes sent.
593
base_events._check_ssl_socket(sock)
594
if self._debug and sock.gettimeout() != 0:
595
raise ValueError("the socket must be non-blocking")
597
return sock.sendto(data, address)
598
except (BlockingIOError, InterruptedError):
601
fut = self.create_future()
603
self._ensure_fd_no_transport(fd)
604
# use a trick with a list in closure to store a mutable state
605
handle = self._add_writer(fd, self._sock_sendto, fut, sock, data,
607
fut.add_done_callback(
608
functools.partial(self._sock_write_done, fd, handle=handle))
611
def _sock_sendto(self, fut, sock, data, address):
613
# Future cancellation can be scheduled on previous loop iteration
616
n = sock.sendto(data, 0, address)
617
except (BlockingIOError, InterruptedError):
619
except (SystemExit, KeyboardInterrupt):
621
except BaseException as exc:
622
fut.set_exception(exc)
626
async def sock_connect(self, sock, address):
627
"""Connect to a remote socket at address.
629
This method is a coroutine.
631
base_events._check_ssl_socket(sock)
632
if self._debug and sock.gettimeout() != 0:
633
raise ValueError("the socket must be non-blocking")
635
if sock.family == socket.AF_INET or (
636
base_events._HAS_IPv6 and sock.family == socket.AF_INET6):
637
resolved = await self._ensure_resolved(
638
address, family=sock.family, type=sock.type, proto=sock.proto,
641
_, _, _, _, address = resolved[0]
643
fut = self.create_future()
644
self._sock_connect(fut, sock, address)
648
# Needed to break cycles when an exception occurs.
651
def _sock_connect(self, fut, sock, address):
654
sock.connect(address)
655
except (BlockingIOError, InterruptedError):
656
# Issue #23618: When the C function connect() fails with EINTR, the
657
# connection runs in background. We have to wait until the socket
658
# becomes writable to be notified when the connection succeed or
660
self._ensure_fd_no_transport(fd)
661
handle = self._add_writer(
662
fd, self._sock_connect_cb, fut, sock, address)
663
fut.add_done_callback(
664
functools.partial(self._sock_write_done, fd, handle=handle))
665
except (SystemExit, KeyboardInterrupt):
667
except BaseException as exc:
668
fut.set_exception(exc)
674
def _sock_write_done(self, fd, fut, handle=None):
675
if handle is None or not handle.cancelled():
676
self.remove_writer(fd)
678
def _sock_connect_cb(self, fut, sock, address):
683
err = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
685
# Jump to any except clause below.
686
raise OSError(err, f'Connect call failed {address}')
687
except (BlockingIOError, InterruptedError):
688
# socket is still registered, the callback will be retried later
690
except (SystemExit, KeyboardInterrupt):
692
except BaseException as exc:
693
fut.set_exception(exc)
699
async def sock_accept(self, sock):
700
"""Accept a connection.
702
The socket must be bound to an address and listening for
703
connections. The return value is a pair (conn, address) where
704
conn is a new socket object usable to send and receive data on the
705
connection, and address is the address bound to the socket on the
706
other end of the connection.
708
base_events._check_ssl_socket(sock)
709
if self._debug and sock.gettimeout() != 0:
710
raise ValueError("the socket must be non-blocking")
711
fut = self.create_future()
712
self._sock_accept(fut, sock)
715
def _sock_accept(self, fut, sock):
716
# gh-153761: _sock_accept must not scheduled with already cancelled future
721
conn, address = sock.accept()
722
conn.setblocking(False)
723
except (BlockingIOError, InterruptedError):
724
self._ensure_fd_no_transport(fd)
725
handle = self._add_reader(fd, self._sock_accept, fut, sock)
726
fut.add_done_callback(
727
functools.partial(self._sock_read_done, fd, handle=handle))
728
except (SystemExit, KeyboardInterrupt):
730
except BaseException as exc:
731
fut.set_exception(exc)
733
fut.set_result((conn, address))
735
async def _sendfile_native(self, transp, file, offset, count):
736
del self._transports[transp._sock_fd]
737
resume_reading = transp.is_reading()
738
transp.pause_reading()
739
await transp._make_empty_waiter()
741
return await self.sock_sendfile(transp._sock, file, offset, count,
744
transp._reset_empty_waiter()
746
transp.resume_reading()
747
self._transports[transp._sock_fd] = transp
749
def _process_events(self, event_list):
750
3
3
for key, mask in event_list:
751
2
2
fileobj, (reader, writer) = key.fileobj, key.data
752
if mask & selectors.EVENT_READ and reader is not None:
753
if reader._cancelled:
754
self._remove_reader(fileobj)
756
self._add_callback(reader)
757
if mask & selectors.EVENT_WRITE and writer is not None:
758
if writer._cancelled:
759
self._remove_writer(fileobj)
761
self._add_callback(writer)
763
def _stop_serving(self, sock):
764
self._remove_reader(sock.fileno())
768
class _SelectorTransport(transports._FlowControlMixin,
769
transports.Transport):
771
max_size = 256 * 1024 # Buffer size passed to recv().
773
# Attribute used in the destructor: it must be set even if the constructor
774
# is not called (see _SelectorSslTransport which may start by raising an
778
def __init__(self, loop, sock, protocol, extra=None, server=None, context=None):
779
super().__init__(extra, loop)
780
self._extra['socket'] = trsock.TransportSocket(sock)
782
self._extra['sockname'] = sock.getsockname()
784
self._extra['sockname'] = None
785
if 'peername' not in self._extra:
787
self._extra['peername'] = sock.getpeername()
789
self._extra['peername'] = None
791
self._sock_fd = sock.fileno()
792
self._context = context
793
self._protocol_connected = False
794
self.set_protocol(protocol)
796
self._server = server
797
self._buffer = collections.deque()
798
self._buffer_size = 0
799
self._conn_lost = 0 # Set when call to connection_lost scheduled.
800
self._closing = False # Set when close() called.
801
self._paused = False # Set when pause_reading() called
803
if self._server is not None:
804
self._server._attach(self)
805
loop._transports[self._sock_fd] = self
808
info = [self.__class__.__name__]
809
if self._sock is None:
810
info.append('closed')
812
info.append('closing')
813
info.append(f'fd={self._sock_fd}')
814
# test if the transport was closed
815
if self._loop is not None and not self._loop.is_closed():
816
polling = _test_selector_event(self._loop._selector,
817
self._sock_fd, selectors.EVENT_READ)
819
info.append('read=polling')
821
info.append('read=idle')
823
polling = _test_selector_event(self._loop._selector,
825
selectors.EVENT_WRITE)
831
bufsize = self.get_write_buffer_size()
832
info.append(f'write=<{state}, bufsize={bufsize}>')
833
return '<{}>'.format(' '.join(info))
836
self._force_close(None)
838
def set_protocol(self, protocol):
839
self._protocol = protocol
840
self._protocol_connected = True
842
def get_protocol(self):
843
return self._protocol
845
def is_closing(self):
848
def is_reading(self):
849
return not self.is_closing() and not self._paused
851
def pause_reading(self):
852
if not self.is_reading():
855
self._loop._remove_reader(self._sock_fd)
856
if self._loop.get_debug():
857
logger.debug("%r pauses reading", self)
859
def resume_reading(self):
860
if self._closing or not self._paused:
863
self._add_reader(self._sock_fd, self._read_ready)
864
if self._loop.get_debug():
865
logger.debug("%r resumes reading", self)
871
self._loop._remove_reader(self._sock_fd)
874
self._loop._remove_writer(self._sock_fd)
875
self._call_soon(self._call_connection_lost, None)
877
def __del__(self, _warn=warnings.warn):
878
if self._sock is not None:
879
_warn(f"unclosed transport {self!r}", ResourceWarning, source=self)
881
if self._server is not None:
882
self._server._detach(self)
884
def _fatal_error(self, exc, message='Fatal error on transport'):
885
# Should be called from exception handler only.
886
if isinstance(exc, OSError):
887
if self._loop.get_debug():
888
logger.debug("%r: %s", self, message, exc_info=True)
890
self._loop.call_exception_handler({
894
'protocol': self._protocol,
896
self._force_close(exc)
898
def _force_close(self, exc):
903
self._buffer_size = 0
904
self._loop._remove_writer(self._sock_fd)
905
if not self._closing:
907
self._loop._remove_reader(self._sock_fd)
909
self._call_soon(self._call_connection_lost, exc)
911
def _call_connection_lost(self, exc):
913
if self._protocol_connected:
914
self._protocol.connection_lost(exc)
916
2
11
self._sock.close()
918
self._protocol = None
920
server = self._server
921
if server is not None:
925
def get_write_buffer_size(self):
926
return self._buffer_size
928
def _add_reader(self, fd, callback, *args):
929
if not self.is_reading():
931
self._loop._add_reader(fd, callback, *args, context=self._context)
933
def _add_writer(self, fd, callback, *args):
934
self._loop._add_writer(fd, callback, *args, context=self._context)
936
def _call_soon(self, callback, *args):
937
self._loop.call_soon(callback, *args, context=self._context)
939
class _SelectorSocketTransport(_SelectorTransport):
941
_start_tls_compatible = True
942
_sendfile_compatible = constants._SendfileMode.TRY_NATIVE
944
def __init__(self, loop, sock, protocol, waiter=None,
945
extra=None, server=None, context=None):
946
self._read_ready_cb = None
947
1
1
super().__init__(loop, sock, protocol, extra, server, context)
949
self._empty_waiter = None
951
self._write_ready = self._write_sendmsg
953
self._write_ready = self._write_send
954
# Disable the Nagle algorithm -- small writes will be
955
# sent without waiting for the TCP ACK. This generally
956
# decreases the latency (in some cases significantly.)
957
base_events._set_nodelay(self._sock)
959
self._call_soon(self._protocol.connection_made, self)
960
# only start reading when connection_made() has been called
961
self._call_soon(self._add_reader, self._sock_fd, self._read_ready)
962
if waiter is not None:
963
# only wake up the waiter when connection_made() has been called
964
self._call_soon(futures._set_result_unless_cancelled, waiter, None)
966
def set_protocol(self, protocol):
967
if isinstance(protocol, protocols.BufferedProtocol):
968
self._read_ready_cb = self._read_ready__get_buffer
970
self._read_ready_cb = self._read_ready__data_received
972
super().set_protocol(protocol)
974
def _read_ready(self):
975
2
62
self._read_ready_cb()
977
def _read_ready__get_buffer(self):
982
buf = self._protocol.get_buffer(-1)
984
raise RuntimeError('get_buffer() returned an empty buffer')
985
except (SystemExit, KeyboardInterrupt):
987
except BaseException as exc:
989
exc, 'Fatal error: protocol.get_buffer() call failed.')
993
nbytes = self._sock.recv_into(buf)
994
except (BlockingIOError, InterruptedError):
996
except (SystemExit, KeyboardInterrupt):
998
except BaseException as exc:
999
self._fatal_error(exc, 'Fatal read error on socket transport')
1003
self._read_ready__on_eof()
1007
self._protocol.buffer_updated(nbytes)
1008
except (SystemExit, KeyboardInterrupt):
1010
except BaseException as exc:
1012
exc, 'Fatal error: protocol.buffer_updated() call failed.')
1014
def _read_ready__data_received(self):
1018
18
20
data = self._sock.recv(self.max_size)
1019
except (BlockingIOError, InterruptedError):
1021
except (SystemExit, KeyboardInterrupt):
1023
except BaseException as exc:
1024
self._fatal_error(exc, 'Fatal read error on socket transport')
1028
self._read_ready__on_eof()
1032
8
40
self._protocol.data_received(data)
1033
except (SystemExit, KeyboardInterrupt):
1035
except BaseException as exc:
1037
exc, 'Fatal error: protocol.data_received() call failed.')
1039
def _read_ready__on_eof(self):
1040
if self._loop.get_debug():
1041
logger.debug("%r received EOF", self)
1044
keep_open = self._protocol.eof_received()
1045
except (SystemExit, KeyboardInterrupt):
1047
except BaseException as exc:
1049
exc, 'Fatal error: protocol.eof_received() call failed.')
1053
# We're keeping the connection open so the
1054
# protocol can write more, but we still can't
1055
# receive more, so remove the reader callback.
1056
self._loop._remove_reader(self._sock_fd)
1060
def write(self, data):
1061
if not isinstance(data, (bytes, bytearray, memoryview)):
1062
raise TypeError(f'data argument must be a bytes, bytearray, or memoryview '
1063
f'object, not {type(data).__name__!r}')
1065
raise RuntimeError('Cannot call write() after write_eof()')
1066
if self._empty_waiter is not None:
1067
raise RuntimeError('unable to write; sendfile is in progress')
1072
if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES:
1073
logger.warning('socket.send() raised exception.')
1074
self._conn_lost += 1
1077
if not self._buffer:
1078
# Optimization: try to send now.
1080
31
31
n = self._sock.send(data)
1081
except (BlockingIOError, InterruptedError):
1083
except (SystemExit, KeyboardInterrupt):
1085
except BaseException as exc:
1086
self._fatal_error(exc, 'Fatal write error on socket transport')
1089
1
1
data = memoryview(data)[n:]
1092
# Not all was written; register write handler.
1093
self._add_writer(self._sock_fd, self._write_ready)
1095
# Add it to the buffer.
1096
self._buffer.append(data)
1097
self._buffer_size += len(data)
1098
self._maybe_pause_protocol()
1100
def _get_sendmsg_buffer(self):
1101
return itertools.islice(self._buffer, SC_IOV_MAX)
1103
def _write_sendmsg(self):
1104
assert self._buffer, 'Data should not be empty'
1108
22
22
nbytes = self._sock.sendmsg(self._get_sendmsg_buffer())
1109
1
1
self._adjust_leftover_buffer(nbytes)
1110
except (BlockingIOError, InterruptedError):
1112
except (SystemExit, KeyboardInterrupt):
1114
except BaseException as exc:
1115
self._loop._remove_writer(self._sock_fd)
1116
self._buffer.clear()
1117
self._buffer_size = 0
1118
self._fatal_error(exc, 'Fatal write error on socket transport')
1119
if self._empty_waiter is not None:
1120
self._empty_waiter.set_exception(exc)
1122
1
1
self._maybe_resume_protocol() # May append to buffer.
1123
if not self._buffer:
1124
self._loop._remove_writer(self._sock_fd)
1125
if self._empty_waiter is not None:
1126
self._empty_waiter.set_result(None)
1127
# gh-156512: don't let _call_connection_lost be called twice
1128
if self._closing and not self._conn_lost:
1129
self._conn_lost += 1
1130
self._call_connection_lost(None)
1132
self._sock.shutdown(socket.SHUT_WR)
1134
def _adjust_leftover_buffer(self, nbytes: int) -> None:
1135
self._buffer_size -= nbytes
1136
buffer = self._buffer
1138
b = buffer.popleft()
1143
buffer.appendleft(b[nbytes:])
1146
def _write_send(self):
1147
assert self._buffer, 'Data should not be empty'
1151
buffer = self._buffer.popleft()
1152
n = self._sock.send(buffer)
1153
if n != len(buffer):
1154
# Not all data was written
1155
self._buffer.appendleft(buffer[n:])
1156
self._buffer_size -= n
1157
except (BlockingIOError, InterruptedError):
1158
self._buffer.appendleft(buffer)
1160
except (SystemExit, KeyboardInterrupt):
1162
except BaseException as exc:
1163
self._loop._remove_writer(self._sock_fd)
1164
self._buffer.clear()
1165
self._buffer_size = 0
1166
self._fatal_error(exc, 'Fatal write error on socket transport')
1167
if self._empty_waiter is not None:
1168
self._empty_waiter.set_exception(exc)
1170
self._maybe_resume_protocol() # May append to buffer.
1171
if not self._buffer:
1172
self._loop._remove_writer(self._sock_fd)
1173
if self._empty_waiter is not None:
1174
self._empty_waiter.set_result(None)
1175
# gh-156512: don't let _call_connection_lost be called twice
1176
if self._closing and not self._conn_lost:
1177
self._conn_lost += 1
1178
self._call_connection_lost(None)
1180
self._sock.shutdown(socket.SHUT_WR)
1182
def write_eof(self):
1183
if self._closing or self._eof:
1186
if not self._buffer:
1187
self._sock.shutdown(socket.SHUT_WR)
1189
def writelines(self, list_of_data):
1191
raise RuntimeError('Cannot call writelines() after write_eof()')
1192
if self._empty_waiter is not None:
1193
raise RuntimeError('unable to writelines; sendfile is in progress')
1194
if not list_of_data:
1198
if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES:
1199
logger.warning('socket.send() raised exception.')
1200
self._conn_lost += 1
1203
for data in list_of_data:
1204
# gh-155888: an empty chunk can never be drained, so never buffer it
1207
self._buffer.append(memoryview(data))
1208
self._buffer_size += len(data)
1209
if not self._buffer:
1212
# If the entire buffer couldn't be written, register a write handler
1214
self._add_writer(self._sock_fd, self._write_ready)
1215
self._maybe_pause_protocol()
1217
def can_write_eof(self):
1220
def _call_connection_lost(self, exc):
1222
1
12
super()._call_connection_lost(exc)
1224
self._write_ready = None
1225
if self._empty_waiter is not None:
1226
self._empty_waiter.set_exception(
1227
ConnectionError("Connection is closed by peer"))
1229
def _make_empty_waiter(self):
1230
if self._empty_waiter is not None:
1231
raise RuntimeError("Empty waiter is already set")
1232
self._empty_waiter = self._loop.create_future()
1233
if not self._buffer:
1234
self._empty_waiter.set_result(None)
1235
return self._empty_waiter
1237
def _reset_empty_waiter(self):
1238
self._empty_waiter = None
1241
self._read_ready_cb = None
1245
class _SelectorDatagramTransport(_SelectorTransport, transports.DatagramTransport):
1247
_buffer_factory = collections.deque
1250
def __init__(self, loop, sock, protocol, address=None,
1251
waiter=None, extra=None):
1252
super().__init__(loop, sock, protocol, extra)
1253
self._address = address
1254
self._buffer_size = 0
1255
self._call_soon(self._protocol.connection_made, self)
1256
# only start reading when connection_made() has been called
1257
self._call_soon(self._add_reader, self._sock_fd, self._read_ready)
1258
if waiter is not None:
1259
# only wake up the waiter when connection_made() has been called
1260
self._call_soon(futures._set_result_unless_cancelled, waiter, None)
1262
def get_write_buffer_size(self):
1263
return self._buffer_size
1265
def _read_ready(self):
1269
data, addr = self._sock.recvfrom(self.max_size)
1270
except (BlockingIOError, InterruptedError):
1272
except OSError as exc:
1273
self._protocol.error_received(exc)
1274
except (SystemExit, KeyboardInterrupt):
1276
except BaseException as exc:
1277
self._fatal_error(exc, 'Fatal read error on datagram transport')
1279
self._protocol.datagram_received(data, addr)
1281
def sendto(self, data, addr=None):
1282
if not isinstance(data, (bytes, bytearray, memoryview)):
1283
raise TypeError(f'data argument must be a bytes-like object, '
1284
f'not {type(data).__name__!r}')
1287
if addr not in (None, self._address):
1289
f'Invalid address: must be None or {self._address}')
1290
addr = self._address
1292
if self._conn_lost and self._address:
1293
if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES:
1294
logger.warning('socket.send() raised exception.')
1295
self._conn_lost += 1
1298
if not self._buffer:
1299
# Attempt to send it right away first.
1301
if self._extra['peername']:
1302
self._sock.send(data)
1304
self._sock.sendto(data, addr)
1306
except (BlockingIOError, InterruptedError):
1307
self._add_writer(self._sock_fd, self._sendto_ready)
1308
except OSError as exc:
1309
self._protocol.error_received(exc)
1311
except (SystemExit, KeyboardInterrupt):
1313
except BaseException as exc:
1315
exc, 'Fatal write error on datagram transport')
1318
# Ensure that what we buffer is immutable.
1319
self._buffer.append((bytes(data), addr))
1320
self._buffer_size += len(data) + self._header_size
1321
self._maybe_pause_protocol()
1323
def _sendto_ready(self):
1325
data, addr = self._buffer.popleft()
1326
self._buffer_size -= len(data) + self._header_size
1328
if self._extra['peername']:
1329
self._sock.send(data)
1331
self._sock.sendto(data, addr)
1332
except (BlockingIOError, InterruptedError):
1333
self._buffer.appendleft((data, addr)) # Try again later.
1334
self._buffer_size += len(data) + self._header_size
1336
except OSError as exc:
1337
self._protocol.error_received(exc)
1339
except (SystemExit, KeyboardInterrupt):
1341
except BaseException as exc:
1343
exc, 'Fatal write error on datagram transport')
1346
self._maybe_resume_protocol() # May append to buffer.
1347
if not self._buffer:
1348
self._loop._remove_writer(self._sock_fd)
1350
self._call_connection_lost(None)