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