GH-116098: Remove dead frame object creation code (GH-116687) · python/cpython@a53cc3f

GitHub

@@ -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):