11import collections
22import subprocess
3+ import sys
4+ import warnings
35
46from . import protocols
57from . import transports
@@ -13,6 +15,7 @@ def __init__(self, loop, protocol, args, shell,
1315 stdin , stdout , stderr , bufsize ,
1416 extra = None , ** kwargs ):
1517 super ().__init__ (extra )
18+ self ._closed = False
1619 self ._protocol = protocol
1720 self ._loop = loop
1821 self ._pid = None
@@ -40,7 +43,10 @@ def __init__(self, loop, protocol, args, shell,
4043 program , self ._pid )
4144
4245 def __repr__ (self ):
43- info = [self .__class__ .__name__ , 'pid=%s' % self ._pid ]
46+ info = [self .__class__ .__name__ ]
47+ if self ._closed :
48+ info .append ('closed' )
49+ info .append ('pid=%s' % self ._pid )
4450 if self ._returncode is not None :
4551 info .append ('returncode=%s' % self ._returncode )
4652
@@ -70,13 +76,23 @@ def _make_read_subprocess_pipe_proto(self, fd):
7076 raise NotImplementedError
7177
7278 def close (self ):
79+ self ._closed = True
7380 for proto in self ._pipes .values ():
7481 if proto is None :
7582 continue
7683 proto .pipe .close ()
7784 if self ._returncode is None :
7885 self .terminate ()
7986
87+ # On Python 3.3 and older, objects with a destructor part of a reference
88+ # cycle are never destroyed. It's not more the case on Python 3.4 thanks
89+ # to the PEP 442.
90+ if sys .version_info >= (3 , 4 ):
91+ def __del__ (self ):
92+ if not self ._closed :
93+ warnings .warn ("unclosed transport %r" % self , ResourceWarning )
94+ self .close ()
95+
8096 def get_pid (self ):
8197 return self ._pid
8298
@@ -104,6 +120,7 @@ def _kill_wait(self):
104120 Function called when an exception is raised during the creation
105121 of a subprocess.
106122 """
123+ self ._closed = True
107124 if self ._loop .get_debug ():
108125 logger .warning ('Exception during subprocess creation, '
109126 'kill the subprocess %r' ,
0 commit comments