Skip to content

Commit

Permalink
gh-94026: Workaround for BlockingIOError in runtest_mp on Emscripten
Browse files Browse the repository at this point in the history
`runtest_mp` test worker now handles :exc:`BlockingIOError` to work around
non-blocking pipes on Emscripten.
  • Loading branch information
tiran committed Jun 23, 2022
1 parent 11e865c commit a937ec9
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
32 changes: 31 additions & 1 deletion Lib/test/libregrtest/runtest_mp.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os.path
import queue
import signal
import select
import subprocess
import sys
import tempfile
Expand Down Expand Up @@ -97,10 +98,39 @@ def run_tests_worker(ns: Namespace, test_name: str) -> NoReturn:
print() # Force a newline (just in case)

# Serialize TestResult as dict in JSON
print(json.dumps(result, cls=EncodeTestResult), flush=True)
dump_result(json.dumps(result, cls=EncodeTestResult), sys.stdout)
sys.exit(0)


def dump_result(data, stream):
"""Dump result data to output stream
Workaround for non-blocking pipes on wasm32-emscripten, GH-94026.
Writes with len(data) <= PIPE_BUF either succeed or fail with EAGAIN
without writing any data. See man write(3) for more details.
"""
data = data.encode(stream.encoding)
# flush buffers, just in case
stream.flush()
fd = stream.fileno()
while data:
exc = None
cur = data[:select.PIPE_BUF]
for _ in range(10):
# retry 10 times with 100 ms magic sleep between retries
try:
written = os.write(fd, cur)
except BlockingIOError as e:
exc = e
time.sleep(0.1)
else:
break
else:
raise exc from None
data = data[written:]


# We do not use a generator so multiple threads can call next().
class MultiprocessIterator:

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

0 comments on commit a937ec9

Please sign in to comment.