thread.start()
thread.join()
+ def test_set_threshold(self):
+ # GH-148613: Setting the GC threshold from another thread could cause a
+ # race between the `gc_should_collect` and `gc_set_threshold` functions.
+ NUM_THREADS = 8
+ NUM_ITERS = 100_000
+ barrier = threading.Barrier(NUM_THREADS)
+
+ class CyclicReference:
+ def __init__(self):
+ self.r = self
+
+ def allocator():
+ barrier.wait()
+ for _ in range(NUM_ITERS):
+ CyclicReference()
+
+ def setter():
+ barrier.wait()
+ for i in range(NUM_ITERS):
+ gc.set_threshold(100 + (i % 100), 10 + (i % 10), 10 + (i % 10))
+
+ current_threshold = gc.get_threshold()
+ try:
+ threads = [Thread(target=allocator) for _ in range(NUM_THREADS - 1)]
+ threads.append(Thread(target=setter))
+ with threading_helper.start_threads(threads):
+ pass
+ finally:
+ gc.set_threshold(*current_threshold)
+
if __name__ == "__main__":
unittest.main()
gcstate->generations[2].threshold = threshold2;
}
#else
+ PyInterpreterState *interp = _PyInterpreterState_GET();
+ _PyEval_StopTheWorld(interp);
gcstate->young.threshold = threshold0;
if (group_right_1) {
gcstate->old[0].threshold = threshold1;
if (group_right_2) {
gcstate->old[1].threshold = threshold2;
}
+ _PyEval_StartTheWorld(interp);
#endif
Py_RETURN_NONE;
}