Skip to content

Commit 9396356

Browse files
committed
Backout c89febab4648 following private feedback by Guido.
(Issue #17807: Generators can now be finalized even when they are part of a reference cycle)
1 parent b710d7e commit 9396356

8 files changed

Lines changed: 244 additions & 334 deletions

File tree

Include/frameobject.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ typedef struct _frame {
3636
non-generator frames. See the save_exc_state and swap_exc_state
3737
functions in ceval.c for details of their use. */
3838
PyObject *f_exc_type, *f_exc_value, *f_exc_traceback;
39-
/* Borrowed referenced to a generator, or NULL */
40-
PyObject *f_gen;
4139

4240
PyThreadState *f_tstate;
4341
int f_lasti; /* Last instruction if called */
@@ -86,13 +84,6 @@ PyAPI_FUNC(void) _PyFrame_DebugMallocStats(FILE *out);
8684
/* Return the line of code the frame is currently executing. */
8785
PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *);
8886

89-
/* Generator support */
90-
PyAPI_FUNC(PyObject *) _PyFrame_YieldingFrom(PyFrameObject *);
91-
PyAPI_FUNC(PyObject *) _PyFrame_GeneratorSend(PyFrameObject *, PyObject *, int exc);
92-
PyAPI_FUNC(PyObject *) _PyFrame_Finalize(PyFrameObject *);
93-
PyAPI_FUNC(int) _PyFrame_CloseIterator(PyObject *);
94-
95-
9687
#ifdef __cplusplus
9788
}
9889
#endif

Include/genobject.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ PyAPI_DATA(PyTypeObject) PyGen_Type;
3333
#define PyGen_CheckExact(op) (Py_TYPE(op) == &PyGen_Type)
3434

3535
PyAPI_FUNC(PyObject *) PyGen_New(struct _frame *);
36-
/* Deprecated, kept for backwards compatibility. */
3736
PyAPI_FUNC(int) PyGen_NeedsFinalizing(PyGenObject *);
3837
PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **);
3938
PyObject *_PyGen_Send(PyGenObject *, PyObject *);

Lib/test/test_generators.py

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,3 @@
1-
import gc
2-
import sys
3-
import unittest
4-
import weakref
5-
6-
from test import support
7-
8-
9-
class FinalizationTest(unittest.TestCase):
10-
11-
def test_frame_resurrect(self):
12-
# A generator frame can be resurrected by a generator's finalization.
13-
def gen():
14-
nonlocal frame
15-
try:
16-
yield
17-
finally:
18-
frame = sys._getframe()
19-
20-
g = gen()
21-
wr = weakref.ref(g)
22-
next(g)
23-
del g
24-
support.gc_collect()
25-
self.assertIs(wr(), None)
26-
self.assertTrue(frame)
27-
del frame
28-
support.gc_collect()
29-
30-
def test_refcycle(self):
31-
# A generator caught in a refcycle gets finalized anyway.
32-
old_garbage = gc.garbage[:]
33-
finalized = False
34-
def gen():
35-
nonlocal finalized
36-
try:
37-
g = yield
38-
yield 1
39-
finally:
40-
finalized = True
41-
42-
g = gen()
43-
next(g)
44-
g.send(g)
45-
self.assertGreater(sys.getrefcount(g), 2)
46-
self.assertFalse(finalized)
47-
del g
48-
support.gc_collect()
49-
self.assertTrue(finalized)
50-
self.assertEqual(gc.garbage, old_garbage)
51-
52-
531
tutorial_tests = """
542
Let's try a simple generator:
553
@@ -1932,7 +1880,6 @@ def printsolution(self, x):
19321880
# so this works as expected in both ways of running regrtest.
19331881
def test_main(verbose=None):
19341882
from test import support, test_generators
1935-
support.run_unittest(__name__)
19361883
support.run_doctest(test_generators, verbose)
19371884

19381885
# This part isn't needed for regrtest, but for running the test directly.

Lib/test/test_sys.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,7 @@ class C(object): pass
764764
nfrees = len(x.f_code.co_freevars)
765765
extras = x.f_code.co_stacksize + x.f_code.co_nlocals +\
766766
ncells + nfrees - 1
767-
check(x, vsize('13P3i' + CO_MAXBLOCKS*'3i' + 'P' + extras*'P'))
767+
check(x, vsize('12P3i' + CO_MAXBLOCKS*'3i' + 'P' + extras*'P'))
768768
# function
769769
def func(): pass
770770
check(func, size('12P'))

Misc/NEWS

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ Core and Builtins
1515
- Issue #17927: Frame objects kept arguments alive if they had been
1616
copied into a cell, even if the cell was cleared.
1717

18-
- Issue #17807: Generators can now be finalized even when they are part of
19-
a reference cycle.
20-
2118
- Issue #1545463: At shutdown, defer finalization of codec modules so
2219
that stderr remains usable.
2320

Modules/gcmodule.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,10 @@ untrack_dicts(PyGC_Head *head)
524524
static int
525525
has_finalizer(PyObject *op)
526526
{
527-
return op->ob_type->tp_del != NULL;
527+
if (PyGen_CheckExact(op))
528+
return PyGen_NeedsFinalizing((PyGenObject *)op);
529+
else
530+
return op->ob_type->tp_del != NULL;
528531
}
529532

530533
/* Move the objects in unreachable with __del__ methods into `finalizers`.

0 commit comments

Comments
 (0)