blob: 7132300a564adc3bd8e98309a21aa2cf5f23dc5c [file] [log] [blame]
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001"""Event loop using a proactor and related classes.
2
3A proactor is a "notify-on-completion" multiplexer. Currently a
4proactor is only implemented on Windows with IOCP.
5"""
6
Victor Stinner8dffc452014-01-25 15:32:06 +01007__all__ = ['BaseProactorEventLoop']
8
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07009import socket
10
11from . import base_events
12from . import constants
13from . import futures
14from . import transports
Guido van Rossumfc29e0f2013-10-17 15:39:45 -070015from .log import logger
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070016
17
Yury Selivanov3cb99142014-02-18 18:41:13 -050018class _ProactorBasePipeTransport(transports._FlowControlMixin,
19 transports.BaseTransport):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070020 """Base class for pipe and socket transports."""
21
22 def __init__(self, loop, sock, protocol, waiter=None,
23 extra=None, server=None):
24 super().__init__(extra)
25 self._set_extra(sock)
26 self._loop = loop
27 self._sock = sock
28 self._protocol = protocol
29 self._server = server
Guido van Rossumebb8e582013-12-04 12:12:07 -080030 self._buffer = None # None or bytearray.
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070031 self._read_fut = None
32 self._write_fut = None
Victor Stinner915bcb02014-02-01 22:49:59 +010033 self._pending_write = 0
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070034 self._conn_lost = 0
35 self._closing = False # Set when close() called.
36 self._eof_written = False
37 if self._server is not None:
Victor Stinnerb28dbac2014-07-11 22:52:21 +020038 self._server._attach()
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070039 self._loop.call_soon(self._protocol.connection_made, self)
40 if waiter is not None:
Victor Stinnerbfff45d2014-07-08 23:57:31 +020041 # wait until protocol.connection_made() has been called
Victor Stinner799a60c2014-07-07 18:08:22 +020042 self._loop.call_soon(waiter._set_result_unless_cancelled, None)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070043
Victor Stinnere912e652014-07-12 03:11:53 +020044 def __repr__(self):
Victor Stinner0e34dc32014-10-12 09:52:11 +020045 info = [self.__class__.__name__]
46 fd = self._sock.fileno()
47 if fd < 0:
48 info.append('closed')
49 elif self._closing:
50 info.append('closing')
51 info.append('fd=%s' % fd)
Victor Stinnere912e652014-07-12 03:11:53 +020052 if self._read_fut is not None:
Victor Stinner18a28dc2014-07-25 13:05:20 +020053 info.append('read=%s' % self._read_fut)
Victor Stinnere912e652014-07-12 03:11:53 +020054 if self._write_fut is not None:
Victor Stinner18a28dc2014-07-25 13:05:20 +020055 info.append("write=%r" % self._write_fut)
Victor Stinnere912e652014-07-12 03:11:53 +020056 if self._buffer:
57 bufsize = len(self._buffer)
58 info.append('write_bufsize=%s' % bufsize)
59 if self._eof_written:
60 info.append('EOF written')
61 return '<%s>' % ' '.join(info)
62
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070063 def _set_extra(self, sock):
64 self._extra['pipe'] = sock
65
66 def close(self):
67 if self._closing:
68 return
69 self._closing = True
70 self._conn_lost += 1
71 if not self._buffer and self._write_fut is None:
72 self._loop.call_soon(self._call_connection_lost, None)
73 if self._read_fut is not None:
74 self._read_fut.cancel()
75
Victor Stinner0ee29c22014-02-19 01:40:41 +010076 def _fatal_error(self, exc, message='Fatal error on pipe transport'):
Victor Stinnere912e652014-07-12 03:11:53 +020077 if isinstance(exc, (BrokenPipeError, ConnectionResetError)):
78 if self._loop.get_debug():
79 logger.debug("%r: %s", self, message, exc_info=True)
80 else:
Yury Selivanov569efa22014-02-18 18:02:19 -050081 self._loop.call_exception_handler({
Victor Stinner0ee29c22014-02-19 01:40:41 +010082 'message': message,
Yury Selivanov569efa22014-02-18 18:02:19 -050083 'exception': exc,
84 'transport': self,
85 'protocol': self._protocol,
86 })
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070087 self._force_close(exc)
88
89 def _force_close(self, exc):
90 if self._closing:
91 return
92 self._closing = True
93 self._conn_lost += 1
94 if self._write_fut:
95 self._write_fut.cancel()
96 if self._read_fut:
97 self._read_fut.cancel()
98 self._write_fut = self._read_fut = None
Victor Stinner915bcb02014-02-01 22:49:59 +010099 self._pending_write = 0
Guido van Rossumebb8e582013-12-04 12:12:07 -0800100 self._buffer = None
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700101 self._loop.call_soon(self._call_connection_lost, exc)
102
103 def _call_connection_lost(self, exc):
104 try:
105 self._protocol.connection_lost(exc)
106 finally:
107 # XXX If there is a pending overlapped read on the other
108 # end then it may fail with ERROR_NETNAME_DELETED if we
109 # just close our end. First calling shutdown() seems to
110 # cure it, but maybe using DisconnectEx() would be better.
111 if hasattr(self._sock, 'shutdown'):
112 self._sock.shutdown(socket.SHUT_RDWR)
113 self._sock.close()
114 server = self._server
115 if server is not None:
Victor Stinnerb28dbac2014-07-11 22:52:21 +0200116 server._detach()
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700117 self._server = None
118
Guido van Rossumebb8e582013-12-04 12:12:07 -0800119 def get_write_buffer_size(self):
Victor Stinner915bcb02014-02-01 22:49:59 +0100120 size = self._pending_write
121 if self._buffer is not None:
122 size += len(self._buffer)
123 return size
Guido van Rossumebb8e582013-12-04 12:12:07 -0800124
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700125
126class _ProactorReadPipeTransport(_ProactorBasePipeTransport,
127 transports.ReadTransport):
128 """Transport for read pipes."""
129
130 def __init__(self, loop, sock, protocol, waiter=None,
131 extra=None, server=None):
132 super().__init__(loop, sock, protocol, waiter, extra, server)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700133 self._paused = False
134 self._loop.call_soon(self._loop_reading)
135
Guido van Rossum57497ad2013-10-18 07:58:20 -0700136 def pause_reading(self):
Guido van Rossumebb8e582013-12-04 12:12:07 -0800137 if self._closing:
138 raise RuntimeError('Cannot pause_reading() when closing')
139 if self._paused:
140 raise RuntimeError('Already paused')
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700141 self._paused = True
Victor Stinnere912e652014-07-12 03:11:53 +0200142 if self._loop.get_debug():
143 logger.debug("%r pauses reading", self)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700144
Guido van Rossum57497ad2013-10-18 07:58:20 -0700145 def resume_reading(self):
Guido van Rossumebb8e582013-12-04 12:12:07 -0800146 if not self._paused:
147 raise RuntimeError('Not paused')
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700148 self._paused = False
149 if self._closing:
150 return
151 self._loop.call_soon(self._loop_reading, self._read_fut)
Victor Stinnere912e652014-07-12 03:11:53 +0200152 if self._loop.get_debug():
153 logger.debug("%r resumes reading", self)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700154
155 def _loop_reading(self, fut=None):
156 if self._paused:
157 return
158 data = None
159
160 try:
161 if fut is not None:
162 assert self._read_fut is fut or (self._read_fut is None and
163 self._closing)
164 self._read_fut = None
165 data = fut.result() # deliver data later in "finally" clause
166
167 if self._closing:
168 # since close() has been called we ignore any read data
169 data = None
170 return
171
172 if data == b'':
173 # we got end-of-file so no need to reschedule a new read
174 return
175
176 # reschedule a new read
177 self._read_fut = self._loop._proactor.recv(self._sock, 4096)
178 except ConnectionAbortedError as exc:
179 if not self._closing:
Victor Stinner0ee29c22014-02-19 01:40:41 +0100180 self._fatal_error(exc, 'Fatal read error on pipe transport')
Victor Stinnerb2614752014-08-25 23:20:52 +0200181 elif self._loop.get_debug():
182 logger.debug("Read error on pipe transport while closing",
183 exc_info=True)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700184 except ConnectionResetError as exc:
185 self._force_close(exc)
186 except OSError as exc:
Victor Stinner0ee29c22014-02-19 01:40:41 +0100187 self._fatal_error(exc, 'Fatal read error on pipe transport')
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700188 except futures.CancelledError:
189 if not self._closing:
190 raise
191 else:
192 self._read_fut.add_done_callback(self._loop_reading)
193 finally:
194 if data:
195 self._protocol.data_received(data)
196 elif data is not None:
Victor Stinnere912e652014-07-12 03:11:53 +0200197 if self._loop.get_debug():
198 logger.debug("%r received EOF", self)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700199 keep_open = self._protocol.eof_received()
200 if not keep_open:
201 self.close()
202
203
Victor Stinnerb60e9ca2014-01-31 14:18:18 +0100204class _ProactorBaseWritePipeTransport(_ProactorBasePipeTransport,
Victor Stinner915bcb02014-02-01 22:49:59 +0100205 transports.WriteTransport):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700206 """Transport for write pipes."""
207
208 def write(self, data):
Guido van Rossumebb8e582013-12-04 12:12:07 -0800209 if not isinstance(data, (bytes, bytearray, memoryview)):
210 raise TypeError('data argument must be byte-ish (%r)',
211 type(data))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700212 if self._eof_written:
Guido van Rossumebb8e582013-12-04 12:12:07 -0800213 raise RuntimeError('write_eof() already called')
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700214
215 if not data:
216 return
217
218 if self._conn_lost:
219 if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES:
Guido van Rossumfc29e0f2013-10-17 15:39:45 -0700220 logger.warning('socket.send() raised exception.')
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700221 self._conn_lost += 1
222 return
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700223
Guido van Rossumebb8e582013-12-04 12:12:07 -0800224 # Observable states:
225 # 1. IDLE: _write_fut and _buffer both None
226 # 2. WRITING: _write_fut set; _buffer None
227 # 3. BACKED UP: _write_fut set; _buffer a bytearray
228 # We always copy the data, so the caller can't modify it
229 # while we're still waiting for the I/O to happen.
230 if self._write_fut is None: # IDLE -> WRITING
231 assert self._buffer is None
232 # Pass a copy, except if it's already immutable.
233 self._loop_writing(data=bytes(data))
234 # XXX Should we pause the protocol at this point
235 # if len(data) > self._high_water? (That would
236 # require keeping track of the number of bytes passed
237 # to a send() that hasn't finished yet.)
238 elif not self._buffer: # WRITING -> BACKED UP
239 # Make a mutable copy which we can extend.
240 self._buffer = bytearray(data)
241 self._maybe_pause_protocol()
242 else: # BACKED UP
243 # Append to buffer (also copies).
244 self._buffer.extend(data)
245 self._maybe_pause_protocol()
246
247 def _loop_writing(self, f=None, data=None):
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700248 try:
249 assert f is self._write_fut
250 self._write_fut = None
Victor Stinner915bcb02014-02-01 22:49:59 +0100251 self._pending_write = 0
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700252 if f:
253 f.result()
Guido van Rossumebb8e582013-12-04 12:12:07 -0800254 if data is None:
255 data = self._buffer
256 self._buffer = None
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700257 if not data:
258 if self._closing:
259 self._loop.call_soon(self._call_connection_lost, None)
260 if self._eof_written:
261 self._sock.shutdown(socket.SHUT_WR)
Victor Stinner915bcb02014-02-01 22:49:59 +0100262 # Now that we've reduced the buffer size, tell the
263 # protocol to resume writing if it was paused. Note that
264 # we do this last since the callback is called immediately
265 # and it may add more data to the buffer (even causing the
266 # protocol to be paused again).
267 self._maybe_resume_protocol()
Guido van Rossumebb8e582013-12-04 12:12:07 -0800268 else:
269 self._write_fut = self._loop._proactor.send(self._sock, data)
Victor Stinner915bcb02014-02-01 22:49:59 +0100270 if not self._write_fut.done():
271 assert self._pending_write == 0
272 self._pending_write = len(data)
273 self._write_fut.add_done_callback(self._loop_writing)
274 self._maybe_pause_protocol()
275 else:
276 self._write_fut.add_done_callback(self._loop_writing)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700277 except ConnectionResetError as exc:
278 self._force_close(exc)
279 except OSError as exc:
Victor Stinner0ee29c22014-02-19 01:40:41 +0100280 self._fatal_error(exc, 'Fatal write error on pipe transport')
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700281
282 def can_write_eof(self):
283 return True
284
285 def write_eof(self):
286 self.close()
287
288 def abort(self):
289 self._force_close(None)
290
291
Victor Stinnerb60e9ca2014-01-31 14:18:18 +0100292class _ProactorWritePipeTransport(_ProactorBaseWritePipeTransport):
293 def __init__(self, *args, **kw):
294 super().__init__(*args, **kw)
295 self._read_fut = self._loop._proactor.recv(self._sock, 16)
296 self._read_fut.add_done_callback(self._pipe_closed)
297
298 def _pipe_closed(self, fut):
299 if fut.cancelled():
300 # the transport has been closed
301 return
Victor Stinner83bdfa02014-02-04 08:57:48 +0100302 assert fut.result() == b''
303 if self._closing:
304 assert self._read_fut is None
305 return
Victor Stinnerb60e9ca2014-01-31 14:18:18 +0100306 assert fut is self._read_fut, (fut, self._read_fut)
307 self._read_fut = None
Victor Stinnerb60e9ca2014-01-31 14:18:18 +0100308 if self._write_fut is not None:
Victor Stinner6f24d832014-02-20 10:33:01 +0100309 self._force_close(BrokenPipeError())
Victor Stinnerb60e9ca2014-01-31 14:18:18 +0100310 else:
311 self.close()
312
313
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700314class _ProactorDuplexPipeTransport(_ProactorReadPipeTransport,
Victor Stinnerb60e9ca2014-01-31 14:18:18 +0100315 _ProactorBaseWritePipeTransport,
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700316 transports.Transport):
317 """Transport for duplex pipes."""
318
319 def can_write_eof(self):
320 return False
321
322 def write_eof(self):
323 raise NotImplementedError
324
325
326class _ProactorSocketTransport(_ProactorReadPipeTransport,
Victor Stinnerb60e9ca2014-01-31 14:18:18 +0100327 _ProactorBaseWritePipeTransport,
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700328 transports.Transport):
329 """Transport for connected sockets."""
330
331 def _set_extra(self, sock):
332 self._extra['socket'] = sock
333 try:
334 self._extra['sockname'] = sock.getsockname()
335 except (socket.error, AttributeError):
Victor Stinnerb2614752014-08-25 23:20:52 +0200336 if self._loop.get_debug():
337 logger.warning("getsockname() failed on %r",
338 sock, exc_info=True)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700339 if 'peername' not in self._extra:
340 try:
341 self._extra['peername'] = sock.getpeername()
342 except (socket.error, AttributeError):
Victor Stinnerb2614752014-08-25 23:20:52 +0200343 if self._loop.get_debug():
344 logger.warning("getpeername() failed on %r",
345 sock, exc_info=True)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700346
347 def can_write_eof(self):
348 return True
349
350 def write_eof(self):
351 if self._closing or self._eof_written:
352 return
353 self._eof_written = True
354 if self._write_fut is None:
355 self._sock.shutdown(socket.SHUT_WR)
356
357
358class BaseProactorEventLoop(base_events.BaseEventLoop):
359
360 def __init__(self, proactor):
361 super().__init__()
Guido van Rossumfc29e0f2013-10-17 15:39:45 -0700362 logger.debug('Using proactor: %s', proactor.__class__.__name__)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700363 self._proactor = proactor
364 self._selector = proactor # convenient alias
Victor Stinner7de26462014-01-11 00:03:21 +0100365 self._self_reading_future = None
366 self._accept_futures = {} # socket file descriptor => Future
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700367 proactor.set_loop(self)
368 self._make_self_pipe()
369
370 def _make_socket_transport(self, sock, protocol, waiter=None,
371 extra=None, server=None):
372 return _ProactorSocketTransport(self, sock, protocol, waiter,
373 extra, server)
374
375 def _make_duplex_pipe_transport(self, sock, protocol, waiter=None,
376 extra=None):
377 return _ProactorDuplexPipeTransport(self,
378 sock, protocol, waiter, extra)
379
380 def _make_read_pipe_transport(self, sock, protocol, waiter=None,
381 extra=None):
382 return _ProactorReadPipeTransport(self, sock, protocol, waiter, extra)
383
384 def _make_write_pipe_transport(self, sock, protocol, waiter=None,
Victor Stinnerb60e9ca2014-01-31 14:18:18 +0100385 extra=None):
386 # We want connection_lost() to be called when other end closes
387 return _ProactorWritePipeTransport(self,
388 sock, protocol, waiter, extra)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700389
390 def close(self):
Victor Stinnerbb2fc5b2014-06-10 10:23:10 +0200391 if self.is_closed():
392 return
Victor Stinnerf328c7d2014-06-23 01:02:37 +0200393 super().close()
Victor Stinnerbb2fc5b2014-06-10 10:23:10 +0200394 self._stop_accept_futures()
395 self._close_self_pipe()
396 self._proactor.close()
397 self._proactor = None
398 self._selector = None
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700399
400 def sock_recv(self, sock, n):
401 return self._proactor.recv(sock, n)
402
403 def sock_sendall(self, sock, data):
404 return self._proactor.send(sock, data)
405
406 def sock_connect(self, sock, address):
Victor Stinner1b0580b2014-02-13 09:24:37 +0100407 try:
408 base_events._check_resolved_address(sock, address)
409 except ValueError as err:
410 fut = futures.Future(loop=self)
411 fut.set_exception(err)
412 return fut
413 else:
414 return self._proactor.connect(sock, address)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700415
416 def sock_accept(self, sock):
417 return self._proactor.accept(sock)
418
419 def _socketpair(self):
420 raise NotImplementedError
421
422 def _close_self_pipe(self):
Victor Stinner7de26462014-01-11 00:03:21 +0100423 if self._self_reading_future is not None:
424 self._self_reading_future.cancel()
425 self._self_reading_future = None
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700426 self._ssock.close()
427 self._ssock = None
428 self._csock.close()
429 self._csock = None
430 self._internal_fds -= 1
431
432 def _make_self_pipe(self):
433 # A self-socket, really. :-)
434 self._ssock, self._csock = self._socketpair()
435 self._ssock.setblocking(False)
436 self._csock.setblocking(False)
437 self._internal_fds += 1
Victor Stinnere912e652014-07-12 03:11:53 +0200438 # don't check the current loop because _make_self_pipe() is called
439 # from the event loop constructor
440 self._call_soon(self._loop_self_reading, (), check_loop=False)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700441
442 def _loop_self_reading(self, f=None):
443 try:
444 if f is not None:
445 f.result() # may raise
446 f = self._proactor.recv(self._ssock, 4096)
447 except:
448 self.close()
449 raise
450 else:
Victor Stinner7de26462014-01-11 00:03:21 +0100451 self._self_reading_future = f
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700452 f.add_done_callback(self._loop_self_reading)
453
454 def _write_to_self(self):
Victor Stinnerfe5649c2014-07-17 22:43:40 +0200455 self._csock.send(b'\0')
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700456
457 def _start_serving(self, protocol_factory, sock, ssl=None, server=None):
Guido van Rossumebb8e582013-12-04 12:12:07 -0800458 if ssl:
459 raise ValueError('IocpEventLoop is incompatible with SSL.')
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700460
461 def loop(f=None):
462 try:
463 if f is not None:
464 conn, addr = f.result()
Victor Stinnere912e652014-07-12 03:11:53 +0200465 if self._debug:
466 logger.debug("%r got a new connection from %r: %r",
467 server, addr, conn)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700468 protocol = protocol_factory()
469 self._make_socket_transport(
470 conn, protocol,
471 extra={'peername': addr}, server=server)
Victor Stinnerbb2fc5b2014-06-10 10:23:10 +0200472 if self.is_closed():
473 return
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700474 f = self._proactor.accept(sock)
Yury Selivanov569efa22014-02-18 18:02:19 -0500475 except OSError as exc:
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700476 if sock.fileno() != -1:
Yury Selivanov569efa22014-02-18 18:02:19 -0500477 self.call_exception_handler({
Victor Stinnerb2614752014-08-25 23:20:52 +0200478 'message': 'Accept failed on a socket',
Yury Selivanov569efa22014-02-18 18:02:19 -0500479 'exception': exc,
480 'socket': sock,
481 })
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700482 sock.close()
Victor Stinnerb2614752014-08-25 23:20:52 +0200483 elif self._debug:
484 logger.debug("Accept failed on socket %r",
485 sock, exc_info=True)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700486 except futures.CancelledError:
487 sock.close()
488 else:
Victor Stinner7de26462014-01-11 00:03:21 +0100489 self._accept_futures[sock.fileno()] = f
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700490 f.add_done_callback(loop)
491
492 self.call_soon(loop)
493
494 def _process_events(self, event_list):
495 pass # XXX hard work currently done in poll
496
Victor Stinnerbb2fc5b2014-06-10 10:23:10 +0200497 def _stop_accept_futures(self):
Victor Stinner7de26462014-01-11 00:03:21 +0100498 for future in self._accept_futures.values():
499 future.cancel()
Victor Stinnerbb2fc5b2014-06-10 10:23:10 +0200500 self._accept_futures.clear()
501
502 def _stop_serving(self, sock):
503 self._stop_accept_futures()
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700504 self._proactor._stop_serving(sock)
505 sock.close()