@@ -35,25 +35,53 @@ def __init__(self, loop, protocol, args, shell,
35
35
self ._pipes [2 ] = None
36
36
37
37
# Create the child process: set the _proc attribute
38
+ self ._loop .create_task (self ._create_child (
39
+ waiter , args = args , shell = shell , stdin = stdin , stdout = stdout ,
40
+ stderr = stderr , bufsize = bufsize , start_kwargs = kwargs ))
41
+
42
+ @coroutine
43
+ def _create_child (self , waiter , args , shell , stdin , stdout , stderr ,
44
+ bufsize , start_kwargs ):
38
45
try :
39
- self ._start (args = args , shell = shell , stdin = stdin , stdout = stdout ,
40
- stderr = stderr , bufsize = bufsize , ** kwargs )
41
- except :
42
- self .close ()
43
- raise
46
+ try :
47
+ start = self ._start (args = args , shell = shell , stdin = stdin ,
48
+ stdout = stdout , stderr = stderr ,
49
+ bufsize = bufsize , ** start_kwargs )
50
+
51
+ if start is not None :
52
+ # _start is not required to be a coroutine
53
+ yield from start
54
+ except :
55
+ self .close ()
56
+ raise
44
57
45
- self ._pid = self ._proc .pid
46
- self ._extra ['subprocess' ] = self ._proc
58
+ self ._pid = self ._proc .pid
59
+ self ._extra ['subprocess' ] = self ._proc
47
60
48
- if self ._loop .get_debug ():
49
- if isinstance (args , (bytes , str )):
50
- program = args
61
+ if self ._loop .get_debug ():
62
+ if isinstance (args , (bytes , str )):
63
+ program = args
64
+ else :
65
+ program = args [0 ]
66
+ logger .debug ('process %r created: pid %s' , program , self ._pid )
67
+
68
+ if self ._closed :
69
+ # transport.close() may have been called concurrently, for
70
+ # instance if _make_subprocess_transport() has been cancelled.
71
+ if self ._proc .stdin :
72
+ self ._proc .stdin .close ()
73
+ if self ._proc .stdout :
74
+ self ._proc .stdout .close ()
75
+ if self ._proc .stderr :
76
+ self ._proc .stderr .close ()
51
77
else :
52
- program = args [0 ]
53
- logger .debug ('process %r created: pid %s' ,
54
- program , self ._pid )
55
-
56
- self ._loop .create_task (self ._connect_pipes (waiter ))
78
+ yield from self ._connect_pipes (waiter )
79
+ except Exception as exc :
80
+ if waiter is not None and not waiter .cancelled ():
81
+ waiter .set_exception (exc )
82
+ else :
83
+ if waiter is not None and not waiter .cancelled ():
84
+ waiter .set_result (None )
57
85
58
86
def __repr__ (self ):
59
87
info = [self .__class__ .__name__ ]
@@ -161,40 +189,33 @@ def kill(self):
161
189
162
190
@coroutine
163
191
def _connect_pipes (self , waiter ):
164
- try :
165
- proc = self ._proc
166
- loop = self ._loop
167
-
168
- if proc .stdin is not None :
169
- _ , pipe = yield from loop .connect_write_pipe (
170
- lambda : WriteSubprocessPipeProto (self , 0 ),
171
- proc .stdin )
172
- self ._pipes [0 ] = pipe
173
-
174
- if proc .stdout is not None :
175
- _ , pipe = yield from loop .connect_read_pipe (
176
- lambda : ReadSubprocessPipeProto (self , 1 ),
177
- proc .stdout )
178
- self ._pipes [1 ] = pipe
179
-
180
- if proc .stderr is not None :
181
- _ , pipe = yield from loop .connect_read_pipe (
182
- lambda : ReadSubprocessPipeProto (self , 2 ),
183
- proc .stderr )
184
- self ._pipes [2 ] = pipe
185
-
186
- assert self ._pending_calls is not None
187
-
188
- loop .call_soon (self ._protocol .connection_made , self )
189
- for callback , data in self ._pending_calls :
190
- loop .call_soon (callback , * data )
191
- self ._pending_calls = None
192
- except Exception as exc :
193
- if waiter is not None and not waiter .cancelled ():
194
- waiter .set_exception (exc )
195
- else :
196
- if waiter is not None and not waiter .cancelled ():
197
- waiter .set_result (None )
192
+ proc = self ._proc
193
+ loop = self ._loop
194
+
195
+ if proc .stdin is not None :
196
+ _ , pipe = yield from loop .connect_write_pipe (
197
+ lambda : WriteSubprocessPipeProto (self , 0 ),
198
+ proc .stdin )
199
+ self ._pipes [0 ] = pipe
200
+
201
+ if proc .stdout is not None :
202
+ _ , pipe = yield from loop .connect_read_pipe (
203
+ lambda : ReadSubprocessPipeProto (self , 1 ),
204
+ proc .stdout )
205
+ self ._pipes [1 ] = pipe
206
+
207
+ if proc .stderr is not None :
208
+ _ , pipe = yield from loop .connect_read_pipe (
209
+ lambda : ReadSubprocessPipeProto (self , 2 ),
210
+ proc .stderr )
211
+ self ._pipes [2 ] = pipe
212
+
213
+ assert self ._pending_calls is not None
214
+
215
+ loop .call_soon (self ._protocol .connection_made , self )
216
+ for callback , data in self ._pending_calls :
217
+ loop .call_soon (callback , * data )
218
+ self ._pending_calls = None
198
219
199
220
def _call (self , cb , * data ):
200
221
if self ._pending_calls is not None :
0 commit comments