Skip to content

Commit a937ec9

Browse files
committed
gh-94026: Workaround for BlockingIOError in runtest_mp on Emscripten
`runtest_mp` test worker now handles :exc:`BlockingIOError` to work around non-blocking pipes on Emscripten.
1 parent 11e865c commit a937ec9

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

Lib/test/libregrtest/runtest_mp.py

+31-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import os.path
44
import queue
55
import signal
6+
import select
67
import subprocess
78
import sys
89
import tempfile
@@ -97,10 +98,39 @@ def run_tests_worker(ns: Namespace, test_name: str) -> NoReturn:
9798
print() # Force a newline (just in case)
9899

99100
# Serialize TestResult as dict in JSON
100-
print(json.dumps(result, cls=EncodeTestResult), flush=True)
101+
dump_result(json.dumps(result, cls=EncodeTestResult), sys.stdout)
101102
sys.exit(0)
102103

103104

105+
def dump_result(data, stream):
106+
"""Dump result data to output stream
107+
108+
Workaround for non-blocking pipes on wasm32-emscripten, GH-94026.
109+
110+
Writes with len(data) <= PIPE_BUF either succeed or fail with EAGAIN
111+
without writing any data. See man write(3) for more details.
112+
"""
113+
data = data.encode(stream.encoding)
114+
# flush buffers, just in case
115+
stream.flush()
116+
fd = stream.fileno()
117+
while data:
118+
exc = None
119+
cur = data[:select.PIPE_BUF]
120+
for _ in range(10):
121+
# retry 10 times with 100 ms magic sleep between retries
122+
try:
123+
written = os.write(fd, cur)
124+
except BlockingIOError as e:
125+
exc = e
126+
time.sleep(0.1)
127+
else:
128+
break
129+
else:
130+
raise exc from None
131+
data = data[written:]
132+
133+
104134
# We do not use a generator so multiple threads can call next().
105135
class MultiprocessIterator:
106136

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
``runtest_mp`` test worker now handles :exc:`BlockingIOError` to work around
2+
non-blocking pipes on Emscripten.

0 commit comments

Comments
 (0)