[pypy-commit] pypy gc-disable: don't call GC hook recursively
antocuni
pypy.commits at gmail.com
Tue Dec 4 05:00:39 EST 2018
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: gc-disable
Changeset: r95407:af1299797766
Date: 2018-12-04 10:59 +0100
http://bitbucket.org/pypy/pypy/changeset/af1299797766/
Log: don't call GC hook recursively
diff --git a/pypy/module/gc/hook.py b/pypy/module/gc/hook.py
--- a/pypy/module/gc/hook.py
+++ b/pypy/module/gc/hook.py
@@ -116,12 +116,24 @@
self.descr_set_on_gc_collect(space, space.w_None)
-class GcMinorHookAction(AsyncAction):
+class NoRecursiveAction(AsyncAction):
+ depth = 0
+
+ def perform(self, ec, frame):
+ if self.depth == 0:
+ try:
+ self.depth += 1
+ return self._do_perform(ec, frame)
+ finally:
+ self.depth -= 1
+
+
+class GcMinorHookAction(NoRecursiveAction):
total_memory_used = 0
pinned_objects = 0
def __init__(self, space):
- AsyncAction.__init__(self, space)
+ NoRecursiveAction.__init__(self, space)
self.w_callable = space.w_None
self.reset()
@@ -144,7 +156,7 @@
self.pinned_objects = NonConstant(-42)
self.fire()
- def perform(self, ec, frame):
+ def _do_perform(self, ec, frame):
w_stats = W_GcMinorStats(
self.count,
self.duration,
@@ -156,12 +168,12 @@
self.space.call_function(self.w_callable, w_stats)
-class GcCollectStepHookAction(AsyncAction):
+class GcCollectStepHookAction(NoRecursiveAction):
oldstate = 0
newstate = 0
def __init__(self, space):
- AsyncAction.__init__(self, space)
+ NoRecursiveAction.__init__(self, space)
self.w_callable = space.w_None
self.reset()
@@ -184,7 +196,7 @@
self.newstate = NonConstant(-42)
self.fire()
- def perform(self, ec, frame):
+ def _do_perform(self, ec, frame):
w_stats = W_GcCollectStepStats(
self.count,
self.duration,
@@ -197,7 +209,7 @@
self.space.call_function(self.w_callable, w_stats)
-class GcCollectHookAction(AsyncAction):
+class GcCollectHookAction(NoRecursiveAction):
num_major_collects = 0
arenas_count_before = 0
arenas_count_after = 0
@@ -206,7 +218,7 @@
rawmalloc_bytes_after = 0
def __init__(self, space):
- AsyncAction.__init__(self, space)
+ NoRecursiveAction.__init__(self, space)
self.w_callable = space.w_None
self.reset()
@@ -227,7 +239,7 @@
self.rawmalloc_bytes_after = NonConstant(r_uint(42))
self.fire()
- def perform(self, ec, frame):
+ def _do_perform(self, ec, frame):
w_stats = W_GcCollectStats(self.count,
self.num_major_collects,
self.arenas_count_before,
diff --git a/pypy/module/gc/test/test_hook.py b/pypy/module/gc/test/test_hook.py
--- a/pypy/module/gc/test/test_hook.py
+++ b/pypy/module/gc/test/test_hook.py
@@ -180,3 +180,22 @@
assert gc.hooks.on_gc_minor is None
assert gc.hooks.on_gc_collect_step is None
assert gc.hooks.on_gc_collect is None
+
+ def test_no_recursive(self):
+ import gc
+ lst = []
+ def on_gc_minor(stats):
+ lst.append((stats.count,
+ stats.duration,
+ stats.total_memory_used,
+ stats.pinned_objects))
+ self.fire_gc_minor(1, 2, 3) # won't fire NOW
+ gc.hooks.on_gc_minor = on_gc_minor
+ self.fire_gc_minor(10, 20, 30)
+ self.fire_gc_minor(40, 50, 60)
+ # the duration for the 2nd call is 41, because it also counts the 1
+ # which was fired recursively
+ assert lst == [
+ (1, 10, 20, 30),
+ (2, 41, 50, 60),
+ ]
More information about the pypy-commit
mailing list