@@ -293,71 +293,6 @@ def gen():
293293 """)
294294assert_python_ok("-c", code)
[email protected]_only
[email protected](Py_GIL_DISABLED, "test requires precise GC scheduling")
298-deftest_sneaky_frame_object(self):
299-300-deftrace(frame, event, arg):
301-"""
302- Don't actually do anything, just force a frame object to be created.
303- """
304-305-defcallback(phase, info):
306-"""
307- Yo dawg, I heard you like frames, so I'm allocating a frame while
308- you're allocating a frame, so you can have a frame while you have a
309- frame!
310- """
311-nonlocalsneaky_frame_object
312-sneaky_frame_object=sys._getframe().f_back.f_back
313-# We're done here:
314-gc.callbacks.remove(callback)
315-316-deff():
317-whileTrue:
318-yield
319-320-old_threshold=gc.get_threshold()
321-old_callbacks=gc.callbacks[:]
322-old_enabled=gc.isenabled()
323-old_trace=sys.gettrace()
324-try:
325-# Stop the GC for a second while we set things up:
326-gc.disable()
327-# Create a paused generator:
328-g=f()
329-next(g)
330-# Move all objects to the oldest generation, and tell the GC to run
331-# on the *very next* allocation:
332-gc.collect()
333-gc.set_threshold(1, 0, 0)
334-sys._clear_internal_caches()
335-# Okay, so here's the nightmare scenario:
336-# - We're tracing the resumption of a generator, which creates a new
337-# frame object.
338-# - The allocation of this frame object triggers a collection
339-# *before* the frame object is actually created.
340-# - During the collection, we request the exact same frame object.
341-# This test does it with a GC callback, but in real code it would
342-# likely be a trace function, weakref callback, or finalizer.
343-# - The collection finishes, and the original frame object is
344-# created. We now have two frame objects fighting over ownership
345-# of the same interpreter frame!
346-sys.settrace(trace)
347-gc.callbacks.append(callback)
348-sneaky_frame_object=None
349-gc.enable()
350-next(g)
351-# g.gi_frame should be the frame object from the callback (the
352-# one that was *requested* second, but *created* first):
353-self.assertIs(g.gi_frame, sneaky_frame_object)
354-finally:
355-gc.set_threshold(*old_threshold)
356-gc.callbacks[:] =old_callbacks
357-sys.settrace(old_trace)
358-ifold_enabled:
359-gc.enable()
[email protected]_only
362297@threading_helper.requires_working_threading()
363298deftest_sneaky_frame_object_teardown(self):