Skip to content

Commit 2b0e2b3

Browse files
authored
Workaround old Python broken multiprocessing shared data structures (#25110)
If running on an old python version that has broken multiprocessing shared data structures, avoid using such data structures. Fixes #25103
1 parent 6812240 commit 2b0e2b3

File tree

1 file changed

+23
-10
lines changed

1 file changed

+23
-10
lines changed

test/parallel_testsuite.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@
2020
seen_class = set()
2121

2222

23+
# Older Python versions have a bug with multiprocessing shared data
24+
# structures. https://github.com/emscripten-core/emscripten/issues/25103
25+
# and https://github.com/python/cpython/issues/71936
26+
def python_multiprocessing_structures_are_buggy():
27+
v = sys.version_info
28+
return (v.major, v.minor, v.micro) <= (3, 12, 7) or (v.major, v.minor, v.micro) == (3, 13, 0)
29+
30+
2331
def run_test(test, failfast_event, lock, progress_counter, num_tests):
2432
# If failfast mode is in effect and any of the tests have failed,
2533
# and then we should abort executing further tests immediately.
@@ -84,9 +92,12 @@ def run(self, result):
8492
print('Using %s parallel test processes' % use_cores, file=sys.stderr)
8593
with multiprocessing.Manager() as manager:
8694
pool = multiprocessing.Pool(use_cores)
87-
failfast_event = manager.Event() if self.failfast else None
88-
progress_counter = manager.Value('i', 0)
89-
lock = manager.Lock()
95+
if python_multiprocessing_structures_are_buggy():
96+
failfast_event = progress_counter = lock = None
97+
else:
98+
failfast_event = manager.Event() if self.failfast else None
99+
progress_counter = manager.Value('i', 0)
100+
lock = manager.Lock()
90101
results = [pool.apply_async(run_test, (t, failfast_event, lock, progress_counter, len(tests))) for t in tests]
91102
results = [r.get() for r in results]
92103
results = [r for r in results if r is not None]
@@ -182,38 +193,40 @@ def stopTest(self, test):
182193
self.buffered_result.duration = self.test_duration
183194

184195
def compute_progress(self):
196+
if not self.lock:
197+
return ''
185198
with self.lock:
186-
val = f'[{int(self.progress_counter.value * 100 / self.num_tests)}%]'
199+
val = f'[{int(self.progress_counter.value * 100 / self.num_tests)}%] '
187200
self.progress_counter.value += 1
188201
return val
189202

190203
def addSuccess(self, test):
191-
print(self.compute_progress(), test, '... ok (%.2fs)' % (self.calculateElapsed()), file=sys.stderr)
204+
print(f'{self.compute_progress()}{test} ... ok ({self.calculateElapsed():.2f}s)', file=sys.stderr)
192205
self.buffered_result = BufferedTestSuccess(test)
193206
self.test_result = 'success'
194207

195208
def addExpectedFailure(self, test, err):
196-
print(self.compute_progress(), test, '... expected failure (%.2fs)' % (self.calculateElapsed()), file=sys.stderr)
209+
print(f'{self.compute_progress()}{test} ... expected failure ({self.calculateElapsed():.2f}s)', file=sys.stderr)
197210
self.buffered_result = BufferedTestExpectedFailure(test, err)
198211
self.test_result = 'expected failure'
199212

200213
def addUnexpectedSuccess(self, test):
201-
print(self.compute_progress(), test, '... unexpected success (%.2fs)' % (self.calculateElapsed()), file=sys.stderr)
214+
print(f'{self.compute_progress()}{test} ... unexpected success ({self.calculateElapsed():.2f}s)', file=sys.stderr)
202215
self.buffered_result = BufferedTestUnexpectedSuccess(test)
203216
self.test_result = 'unexpected success'
204217

205218
def addSkip(self, test, reason):
206-
print(self.compute_progress(), test, "... skipped '%s'" % reason, file=sys.stderr)
219+
print(f"{self.compute_progress()}{test} ... skipped '{reason}'", file=sys.stderr)
207220
self.buffered_result = BufferedTestSkip(test, reason)
208221
self.test_result = 'skipped'
209222

210223
def addFailure(self, test, err):
211-
print(self.compute_progress(), test, '... FAIL', file=sys.stderr)
224+
print(f'{self.compute_progress()}{test} ... FAIL', file=sys.stderr)
212225
self.buffered_result = BufferedTestFailure(test, err)
213226
self.test_result = 'failed'
214227

215228
def addError(self, test, err):
216-
print(self.compute_progress(), test, '... ERROR', file=sys.stderr)
229+
print(f'{self.compute_progress()}{test} ... ERROR', file=sys.stderr)
217230
self.buffered_result = BufferedTestError(test, err)
218231
self.test_result = 'errored'
219232

0 commit comments

Comments
 (0)