asyncio: sync with Tulip

* PipeHandle now uses None instead of -1 for a closed handle
* Sort imports in windows_utils.
* Fix test_events on Python older than 3.5. Skip SSL tests on the
  ProactorEventLoop if ssl.MemoryIO is missing
* Fix BaseEventLoop._create_connection_transport(). Close the transport if the
  creation of the transport (if the waiter) gets an exception.
* _ProactorBasePipeTransport now sets _sock to None when the transport is
  closed.
* Fix BaseSubprocessTransport.close(). Ignore pipes for which the protocol is
  not set yet (still equal to None).
* TestLoop.close() now calls the close() method of the parent class
  (BaseEventLoop).
* Cleanup BaseSelectorEventLoop: create the protocol on a separated line for
  readability and ease debugging.
* Fix BaseSubprocessTransport._kill_wait(). Set the _returncode attribute, so
  close() doesn't try to terminate the process.
* Tests: explicitly close event loops and transports
* UNIX pipe transports: add closed/closing in repr(). Add "closed" or "closing"
  state in the __repr__() method of _UnixReadPipeTransport and
  _UnixWritePipeTransport classes.
This commit is contained in:
Victor Stinner 2015-01-15 00:04:21 +01:00
parent b92626df5c
commit 29ad0111bd
12 changed files with 57 additions and 11 deletions

View file

@ -634,7 +634,12 @@ class BaseEventLoop(events.AbstractEventLoop):
else:
transport = self._make_socket_transport(sock, protocol, waiter)
yield from waiter
try:
yield from waiter
except Exception as exc:
transport.close()
raise
return transport, protocol
@coroutine

View file

@ -71,6 +71,8 @@ class BaseSubprocessTransport(transports.SubprocessTransport):
def close(self):
for proto in self._pipes.values():
if proto is None:
continue
proto.pipe.close()
if self._returncode is None:
self.terminate()
@ -119,7 +121,7 @@ class BaseSubprocessTransport(transports.SubprocessTransport):
proc.kill()
except ProcessLookupError:
pass
proc.wait()
self._returncode = proc.wait()
@coroutine
def _post_init(self):

View file

@ -111,6 +111,7 @@ class _ProactorBasePipeTransport(transports._FlowControlMixin,
if hasattr(self._sock, 'shutdown'):
self._sock.shutdown(socket.SHUT_RDWR)
self._sock.close()
self._sock = None
server = self._server
if server is not None:
server._detach()

View file

@ -182,13 +182,14 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
else:
raise # The event loop will catch, log and ignore it.
else:
protocol = protocol_factory()
if sslcontext:
self._make_ssl_transport(
conn, protocol_factory(), sslcontext,
conn, protocol, sslcontext,
server_side=True, extra={'peername': addr}, server=server)
else:
self._make_socket_transport(
conn, protocol_factory(), extra={'peername': addr},
conn, protocol , extra={'peername': addr},
server=server)
# It's now up to the protocol to handle the connection.

View file

@ -307,6 +307,7 @@ class TestLoop(base_events.BaseEventLoop):
self._time += advance
def close(self):
super().close()
if self._check_on_close:
try:
self._gen.send(0)

View file

@ -301,7 +301,12 @@ class _UnixReadPipeTransport(transports.ReadTransport):
self._loop.call_soon(waiter._set_result_unless_cancelled, None)
def __repr__(self):
info = [self.__class__.__name__, 'fd=%s' % self._fileno]
info = [self.__class__.__name__]
if self._pipe is None:
info.append('closed')
elif self._closing:
info.append('closing')
info.append('fd=%s' % self._fileno)
if self._pipe is not None:
polling = selector_events._test_selector_event(
self._loop._selector,
@ -404,7 +409,12 @@ class _UnixWritePipeTransport(transports._FlowControlMixin,
self._loop.call_soon(waiter._set_result_unless_cancelled, None)
def __repr__(self):
info = [self.__class__.__name__, 'fd=%s' % self._fileno]
info = [self.__class__.__name__]
if self._pipe is None:
info.append('closed')
elif self._closing:
info.append('closing')
info.append('fd=%s' % self._fileno)
if self._pipe is not None:
polling = selector_events._test_selector_event(
self._loop._selector,

View file

@ -7,13 +7,13 @@ import sys
if sys.platform != 'win32': # pragma: no cover
raise ImportError('win32 only')
import socket
import _winapi
import itertools
import msvcrt
import os
import socket
import subprocess
import tempfile
import _winapi
__all__ = ['socketpair', 'pipe', 'Popen', 'PIPE', 'PipeHandle']
@ -136,7 +136,7 @@ class PipeHandle:
self._handle = handle
def __repr__(self):
if self._handle != -1:
if self._handle is not None:
handle = 'handle=%r' % self._handle
else:
handle = 'closed'
@ -150,9 +150,9 @@ class PipeHandle:
return self._handle
def close(self, *, CloseHandle=_winapi.CloseHandle):
if self._handle != -1:
if self._handle is not None:
CloseHandle(self._handle)
self._handle = -1
self._handle = None
__del__ = close