@@ -70,7 +70,9 @@ def run_test_in_subprocess(testname: str, ns: Namespace) -> subprocess.Popen:
70
70
kw ['start_new_session' ] = True
71
71
return subprocess .Popen (cmd ,
72
72
stdout = subprocess .PIPE ,
73
- stderr = subprocess .PIPE ,
73
+ # bpo-45410: Write stderr into stdout to keep
74
+ # messages order
75
+ stderr = subprocess .STDOUT ,
74
76
universal_newlines = True ,
75
77
close_fds = (os .name != 'nt' ),
76
78
cwd = os_helper .SAVEDCWD ,
@@ -114,8 +116,8 @@ def stop(self):
114
116
115
117
class MultiprocessResult (NamedTuple ):
116
118
result : TestResult
119
+ # bpo-45410: stderr is written into stdout to keep messages order
117
120
stdout : str
118
- stderr : str
119
121
error_msg : str
120
122
121
123
@@ -195,11 +197,10 @@ def mp_result_error(
195
197
self ,
196
198
test_result : TestResult ,
197
199
stdout : str = '' ,
198
- stderr : str = '' ,
199
200
err_msg = None
200
201
) -> MultiprocessResult :
201
202
test_result .duration_sec = time .monotonic () - self .start_time
202
- return MultiprocessResult (test_result , stdout , stderr , err_msg )
203
+ return MultiprocessResult (test_result , stdout , err_msg )
203
204
204
205
def _run_process (self , test_name : str ) -> tuple [int , str , str ]:
205
206
self .start_time = time .monotonic ()
@@ -223,13 +224,14 @@ def _run_process(self, test_name: str) -> tuple[int, str, str]:
223
224
raise ExitThread
224
225
225
226
try :
226
- stdout , stderr = popen .communicate (timeout = self .timeout )
227
+ # bpo-45410: stderr is written into stdout
228
+ stdout , _ = popen .communicate (timeout = self .timeout )
227
229
retcode = popen .returncode
228
230
assert retcode is not None
229
231
except subprocess .TimeoutExpired :
230
232
if self ._stopped :
231
- # kill() has been called: communicate() fails
232
- # on reading closed stdout/stderr
233
+ # kill() has been called: communicate() fails on reading
234
+ # closed stdout
233
235
raise ExitThread
234
236
235
237
# On timeout, kill the process
@@ -238,20 +240,19 @@ def _run_process(self, test_name: str) -> tuple[int, str, str]:
238
240
# None means TIMEOUT for the caller
239
241
retcode = None
240
242
# bpo-38207: Don't attempt to call communicate() again: on it
241
- # can hang until all child processes using stdout and stderr
243
+ # can hang until all child processes using stdout
242
244
# pipes completes.
243
- stdout = stderr = ''
245
+ stdout = ''
244
246
except OSError :
245
247
if self ._stopped :
246
248
# kill() has been called: communicate() fails
247
- # on reading closed stdout/stderr
249
+ # on reading closed stdout
248
250
raise ExitThread
249
251
raise
250
252
else :
251
253
stdout = stdout .strip ()
252
- stderr = stderr .rstrip ()
253
254
254
- return (retcode , stdout , stderr )
255
+ return (retcode , stdout )
255
256
except :
256
257
self ._kill ()
257
258
raise
@@ -261,10 +262,10 @@ def _run_process(self, test_name: str) -> tuple[int, str, str]:
261
262
self .current_test_name = None
262
263
263
264
def _runtest (self , test_name : str ) -> MultiprocessResult :
264
- retcode , stdout , stderr = self ._run_process (test_name )
265
+ retcode , stdout = self ._run_process (test_name )
265
266
266
267
if retcode is None :
267
- return self .mp_result_error (Timeout (test_name ), stdout , stderr )
268
+ return self .mp_result_error (Timeout (test_name ), stdout )
268
269
269
270
err_msg = None
270
271
if retcode != 0 :
@@ -282,10 +283,9 @@ def _runtest(self, test_name: str) -> MultiprocessResult:
282
283
err_msg = "Failed to parse worker JSON: %s" % exc
283
284
284
285
if err_msg is not None :
285
- return self .mp_result_error (ChildError (test_name ),
286
- stdout , stderr , err_msg )
286
+ return self .mp_result_error (ChildError (test_name ), stdout , err_msg )
287
287
288
- return MultiprocessResult (result , stdout , stderr , err_msg )
288
+ return MultiprocessResult (result , stdout , err_msg )
289
289
290
290
def run (self ) -> None :
291
291
while not self ._stopped :
@@ -309,10 +309,8 @@ def run(self) -> None:
309
309
def _wait_completed (self ) -> None :
310
310
popen = self ._popen
311
311
312
- # stdout and stderr must be closed to ensure that communicate()
313
- # does not hang
312
+ # stdout must be closed to ensure that communicate() does not hang
314
313
popen .stdout .close ()
315
- popen .stderr .close ()
316
314
317
315
try :
318
316
popen .wait (JOIN_TIMEOUT )
@@ -449,8 +447,6 @@ def _process_result(self, item: QueueOutput) -> bool:
449
447
450
448
if mp_result .stdout :
451
449
print (mp_result .stdout , flush = True )
452
- if mp_result .stderr and not self .ns .pgo :
453
- print (mp_result .stderr , file = sys .stderr , flush = True )
454
450
455
451
if must_stop (mp_result .result , self .ns ):
456
452
return True
0 commit comments