| 166 | ssl_handshake_timeout, ssl_shutdown_timeout, context) |
| 167 | |
| 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): |
| 178 | try: |
| 179 | conn, addr = sock.accept() |
| 180 | if self._debug: |
| 181 | logger.debug("%r got a new connection from %r: %r", |
| 182 | server, addr, conn) |
| 183 | conn.setblocking(False) |
| 184 | except ConnectionAbortedError: |
| 185 | # Discard connections that were aborted before accept(). |
| 186 | continue |
| 187 | except (BlockingIOError, InterruptedError): |
| 188 | # Early exit because of a signal or |
| 189 | # the socket accept buffer is empty. |
| 190 | return |
| 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', |
| 200 | 'exception': exc, |
| 201 | 'socket': trsock.TransportSocket(sock), |
| 202 | }) |
| 203 | self._remove_reader(sock.fileno()) |
| 204 | self.call_later(constants.ACCEPT_RETRY_DELAY, |
| 205 | self._start_serving, |
| 206 | protocol_factory, sock, sslcontext, server, |
| 207 | backlog, ssl_handshake_timeout, |
| 208 | ssl_shutdown_timeout, context) |
| 209 | else: |
| 210 | raise # The event loop will catch, log and ignore it. |
| 211 | else: |
| 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 | self.create_task(accept, context=conn_context) |
| 218 | |
| 219 | async def _accept_connection2( |
| 220 | self, protocol_factory, conn, extra, |