diff --git a/hypothesis-python/src/hypothesis/internal/conjecture/junkdrawer.py b/hypothesis-python/src/hypothesis/internal/conjecture/junkdrawer.py index 7a4257a7e03..c40f70606a3 100644 --- a/hypothesis-python/src/hypothesis/internal/conjecture/junkdrawer.py +++ b/hypothesis-python/src/hypothesis/internal/conjecture/junkdrawer.py @@ -414,10 +414,20 @@ def _gc_callback(phase, _info): # pragma: no cover # called outside coverage b def gc_cumulative_time() -> float: global _gc_initialized if not _gc_initialized: - # Indirection via lambda to simplify monkeypatching of the callback fn - # - gc.callbacks can't be reassigned and hence is not suitable for - # monkeypatching directly. Don't remove this lambda without considering - # implications in tests/conftest.py. - gc.callbacks.insert(0, lambda *args: _gc_callback(*args)) + + def gc_callback(phase, info): + # There's not much that can fail here, but to avoid flakiness + # if collection is triggered near the recursion limit we temporarily + # bump to ensure there's headroom. Assuming the limit wasn't already + # exceeded by calling *this* method of course, but there's nothing we + # can do about that. + orig_recursionlimit = sys.getrecursionlimit() + sys.setrecursionlimit(orig_recursionlimit + 5) + try: + _gc_callback(phase, info) + finally: + sys.setrecursionlimit(orig_recursionlimit) + + gc.callbacks.insert(0, gc_callback) _gc_initialized = True return _gc_cumulative_time