Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0122ab2

Browse files
authored
[3.11]gh-94026: Buffer regrtest worker stdout in temporary file (GH-94253) (GH-94408)
Co-authored-by: Victor Stinner <vstinner@python.org>.Co-authored-by: Christian Heimes <christian@python.org>
1 parentaaa85b5 commit0122ab2

File tree

1 file changed

+28
-26
lines changed

1 file changed

+28
-26
lines changed

‎Lib/test/libregrtest/runtest_mp.py‎

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
importsignal
66
importsubprocess
77
importsys
8+
importtempfile
89
importthreading
910
importtime
1011
importtraceback
11-
fromtypingimportNamedTuple,NoReturn,Literal,Any
12+
fromtypingimportNamedTuple,NoReturn,Literal,Any,TextIO
1213

1314
fromtestimportsupport
1415
fromtest.supportimportos_helper
@@ -51,7 +52,7 @@ def parse_worker_args(worker_args) -> tuple[Namespace, str]:
5152
return (ns,test_name)
5253

5354

54-
defrun_test_in_subprocess(testname:str,ns:Namespace)->subprocess.Popen:
55+
defrun_test_in_subprocess(testname:str,ns:Namespace,stdout_fh:TextIO)->subprocess.Popen:
5556
ns_dict=vars(ns)
5657
worker_args= (ns_dict,testname)
5758
worker_args=json.dumps(worker_args)
@@ -67,18 +68,17 @@ def run_test_in_subprocess(testname: str, ns: Namespace) -> subprocess.Popen:
6768
# Running the child from the same working directory as regrtest's original
6869
# invocation ensures that TEMPDIR for the child is the same when
6970
# sysconfig.is_python_build() is true. See issue 15300.
70-
kw= {}
71+
kw=dict(
72+
stdout=stdout_fh,
73+
# bpo-45410: Write stderr into stdout to keep messages order
74+
stderr=stdout_fh,
75+
text=True,
76+
close_fds=(os.name!='nt'),
77+
cwd=os_helper.SAVEDCWD,
78+
)
7179
ifUSE_PROCESS_GROUP:
7280
kw['start_new_session']=True
73-
returnsubprocess.Popen(cmd,
74-
stdout=subprocess.PIPE,
75-
# bpo-45410: Write stderr into stdout to keep
76-
# messages order
77-
stderr=subprocess.STDOUT,
78-
universal_newlines=True,
79-
close_fds=(os.name!='nt'),
80-
cwd=os_helper.SAVEDCWD,
81-
**kw)
81+
returnsubprocess.Popen(cmd,**kw)
8282

8383

8484
defrun_tests_worker(ns:Namespace,test_name:str)->NoReturn:
@@ -204,12 +204,12 @@ def mp_result_error(
204204
test_result.duration_sec=time.monotonic()-self.start_time
205205
returnMultiprocessResult(test_result,stdout,err_msg)
206206

207-
def_run_process(self,test_name:str)->tuple[int,str,str]:
207+
def_run_process(self,test_name:str,stdout_fh:TextIO)->int:
208208
self.start_time=time.monotonic()
209209

210210
self.current_test_name=test_name
211211
try:
212-
popen=run_test_in_subprocess(test_name,self.ns)
212+
popen=run_test_in_subprocess(test_name,self.ns,stdout_fh)
213213

214214
self._killed=False
215215
self._popen=popen
@@ -226,10 +226,10 @@ def _run_process(self, test_name: str) -> tuple[int, str, str]:
226226
raiseExitThread
227227

228228
try:
229-
# bpo-45410: stderr is written into stdout
230-
stdout,_=popen.communicate(timeout=self.timeout)
231-
retcode=popen.returncode
229+
# gh-94026: stdout+stderr are written to tempfile
230+
retcode=popen.wait(timeout=self.timeout)
232231
assertretcodeisnotNone
232+
returnretcode
233233
exceptsubprocess.TimeoutExpired:
234234
ifself._stopped:
235235
# kill() has been called: communicate() fails on reading
@@ -244,17 +244,12 @@ def _run_process(self, test_name: str) -> tuple[int, str, str]:
244244
# bpo-38207: Don't attempt to call communicate() again: on it
245245
# can hang until all child processes using stdout
246246
# pipes completes.
247-
stdout=''
248247
exceptOSError:
249248
ifself._stopped:
250249
# kill() has been called: communicate() fails
251250
# on reading closed stdout
252251
raiseExitThread
253252
raise
254-
else:
255-
stdout=stdout.strip()
256-
257-
return (retcode,stdout)
258253
except:
259254
self._kill()
260255
raise
@@ -264,7 +259,17 @@ def _run_process(self, test_name: str) -> tuple[int, str, str]:
264259
self.current_test_name=None
265260

266261
def_runtest(self,test_name:str)->MultiprocessResult:
267-
retcode,stdout=self._run_process(test_name)
262+
# gh-94026: Write stdout+stderr to a tempfile as workaround for
263+
# non-blocking pipes on Emscripten with NodeJS.
264+
withtempfile.TemporaryFile(
265+
'w+',encoding=sys.stdout.encoding
266+
)asstdout_fh:
267+
# gh-93353: Check for leaked temporary files in the parent process,
268+
# since the deletion of temporary files can happen late during
269+
# Python finalization: too late for libregrtest.
270+
retcode=self._run_process(test_name,stdout_fh)
271+
stdout_fh.seek(0)
272+
stdout=stdout_fh.read().strip()
268273

269274
ifretcodeisNone:
270275
returnself.mp_result_error(Timeout(test_name),stdout)
@@ -311,9 +316,6 @@ def run(self) -> None:
311316
def_wait_completed(self)->None:
312317
popen=self._popen
313318

314-
# stdout must be closed to ensure that communicate() does not hang
315-
popen.stdout.close()
316-
317319
try:
318320
popen.wait(JOIN_TIMEOUT)
319321
except (subprocess.TimeoutExpired,OSError)asexc:

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp