Skip to content

Commit 1aa69a7

Browse files
jacobtylerwallsnessita
authored andcommitted
Fixed #36678 -- Limited retries in ParallelTestRunner.
Thanks Natalia Bidart for the review.
1 parent 787cc96 commit 1aa69a7

2 files changed

Lines changed: 22 additions & 4 deletions

File tree

django/test/runner.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import argparse
22
import ctypes
33
import faulthandler
4+
import functools
45
import hashlib
56
import io
67
import itertools
@@ -485,6 +486,16 @@ def _init_worker(
485486
)
486487

487488

489+
def _safe_init_worker(init_worker, counter, *args, **kwargs):
490+
try:
491+
init_worker(counter, *args, **kwargs)
492+
except Exception:
493+
with counter.get_lock():
494+
# Set a value that will not increment above zero any time soon.
495+
counter.value = -1000
496+
raise
497+
498+
488499
def _run_subsuite(args):
489500
"""
490501
Run a suite of tests with a RemoteTestRunner and return a RemoteTestResult.
@@ -558,7 +569,7 @@ def run(self, result):
558569
counter = multiprocessing.Value(ctypes.c_int, 0)
559570
pool = multiprocessing.Pool(
560571
processes=self.processes,
561-
initializer=self.init_worker.__func__,
572+
initializer=functools.partial(_safe_init_worker, self.init_worker.__func__),
562573
initargs=[
563574
counter,
564575
self.initial_settings,
@@ -585,7 +596,11 @@ def run(self, result):
585596

586597
try:
587598
subsuite_index, events = test_results.next(timeout=0.1)
588-
except multiprocessing.TimeoutError:
599+
except multiprocessing.TimeoutError as err:
600+
if counter.value < 0:
601+
err.add_note("ERROR: _init_worker failed, see prior traceback")
602+
pool.close()
603+
raise
589604
continue
590605
except StopIteration:
591606
pool.close()

tests/test_runner/tests.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55
import collections.abc
6+
import functools
67
import multiprocessing
78
import os
89
import sys
@@ -738,8 +739,10 @@ def run_suite(self, suite, **kwargs):
738739
"test_runner_apps.simple.tests",
739740
]
740741
)
741-
# Initializer must be a function.
742-
self.assertIs(mocked_pool.call_args.kwargs["initializer"], _init_worker)
742+
# Initializer must be a partial function binding _init_worker.
743+
initializer = mocked_pool.call_args.kwargs["initializer"]
744+
self.assertIsInstance(initializer, functools.partial)
745+
self.assertIs(initializer.args[0], _init_worker)
743746
initargs = mocked_pool.call_args.kwargs["initargs"]
744747
self.assertEqual(len(initargs), 7)
745748
self.assertEqual(initargs[5], True) # debug_mode

0 commit comments

Comments
 (0)