@@ -293,71 +293,6 @@ def gen():
293
293
""" )
294
294
assert_python_ok ("-c" , code )
295
295
296
- @support .cpython_only
297
- @unittest .skipIf (Py_GIL_DISABLED , "test requires precise GC scheduling" )
298
- def test_sneaky_frame_object (self ):
299
-
300
- def trace (frame , event , arg ):
301
- """
302
- Don't actually do anything, just force a frame object to be created.
303
- """
304
-
305
- def callback (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
- nonlocal sneaky_frame_object
312
- sneaky_frame_object = sys ._getframe ().f_back .f_back
313
- # We're done here:
314
- gc .callbacks .remove (callback )
315
-
316
- def f ():
317
- while True :
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
- if old_enabled :
359
- gc .enable ()
360
-
361
296
@support .cpython_only
362
297
@threading_helper .requires_working_threading ()
363
298
def test_sneaky_frame_object_teardown (self ):
0 commit comments