
I (and Guido) are accepting PEP 442 (Safe object finalization) on the condition that finalizers are only ever called once globally. Congratulations to Antoine on writing yet another PEP that deeply touches the core language in a way that everyone can agree is an improvement.. I look forward to reviewing the code. -- Regards, Benjamin

Le 05/06/2013 18:10, Benjamin Peterson a écrit :
I (and Guido) are accepting PEP 442 (Safe object finalization) on the condition that finalizers are only ever called once globally.
Congratulations to Antoine on writing yet another PEP that deeply touches the core language in a way that everyone can agree is an improvement.. I look forward to reviewing the code.
Thank you! Antoine (on holiday - is anyone I know in Hungary?).
-- Regards, Benjamin

On Wed, 5 Jun 2013 09:10:54 -0700 Benjamin Peterson <benjamin@python.org> wrote:
I (and Guido) are accepting PEP 442 (Safe object finalization) on the condition that finalizers are only ever called once globally.
Ok, so there's an issue with that condition: it can't be upholded on non-GC objects. Creating a non-GC object is quite obscure and rare, though, since it requires basically a class with no __dict__ and an empty __slots__: class C: __slots__ = () survivors = [] def __del__(self): self.survivors.append(self) In this case, a C instance's __del__ will be called every time destruction is attempted, not only once. Is that a realistic problem? Regards Antoine.

On Fri, 14 Jun 2013 19:34:41 +0200 Antoine Pitrou <solipsis@pitrou.net> wrote:
On Wed, 5 Jun 2013 09:10:54 -0700 Benjamin Peterson <benjamin@python.org> wrote:
I (and Guido) are accepting PEP 442 (Safe object finalization) on the condition that finalizers are only ever called once globally.
Ok, so there's an issue with that condition: it can't be upholded on non-GC objects. Creating a non-GC object is quite obscure and rare, though, since it requires basically a class with no __dict__ and an empty __slots__: [...]
One more problem, albeit minor: there's a test_descr failure in some part marked as "CPython implementation detail": ====================================================================== FAIL: test_subtype_resurrection (test.test_descr.ClassPropertiesAndMethods) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/antoine/cpython/finalize/Lib/test/test_descr.py", line 3749, in test_subtype_resurrection self.assertEqual(len(C.container), 1) AssertionError: 0 != 1 However, the third-party test suites (Tornado, Tulip, SQLAlchemy, Django, zope.interface) show no regressions. Regards Antoine.

On 15 June 2013 03:34, Antoine Pitrou <solipsis@pitrou.net> wrote:
On Wed, 5 Jun 2013 09:10:54 -0700 Benjamin Peterson <benjamin@python.org> wrote:
I (and Guido) are accepting PEP 442 (Safe object finalization) on the condition that finalizers are only ever called once globally.
Ok, so there's an issue with that condition: it can't be upholded on non-GC objects. Creating a non-GC object is quite obscure and rare, though, since it requires basically a class with no __dict__ and an empty __slots__:
class C: __slots__ = () survivors = []
def __del__(self): self.survivors.append(self)
In this case, a C instance's __del__ will be called every time destruction is attempted, not only once. Is that a realistic problem?
So, to trigger that __del__() method a second time, such an object would have to be: 1. Defined in the first place (the use cases for stateless objects with destructors seem rare...) 2. Hanging off a reference cycle 3. Which then gets resurrected If it isn't easy to fix by changing the way such classes are constructed by typeobject.c (i.e. force them to be GC-aware when they define a __del__ method, since they may still be hanging off the edge of a reference cycle, even if they can't form one themselves), I'd say chalk it up as a CPython wart and not worry about it for now. As far as the test_subtype_resurrection failure goes, I think the associated comment says it all: "(On non-CPython implementations, however, __del__ is typically not called again.)" The test should just be rewritten to check that __del__ is only called once in the face of resurrection. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Sat, 15 Jun 2013 14:57:49 +1000 Nick Coghlan <ncoghlan@gmail.com> wrote:
On 15 June 2013 03:34, Antoine Pitrou <solipsis@pitrou.net> wrote:
On Wed, 5 Jun 2013 09:10:54 -0700 Benjamin Peterson <benjamin@python.org> wrote:
I (and Guido) are accepting PEP 442 (Safe object finalization) on the condition that finalizers are only ever called once globally.
Ok, so there's an issue with that condition: it can't be upholded on non-GC objects. Creating a non-GC object is quite obscure and rare, though, since it requires basically a class with no __dict__ and an empty __slots__:
class C: __slots__ = () survivors = []
def __del__(self): self.survivors.append(self)
In this case, a C instance's __del__ will be called every time destruction is attempted, not only once. Is that a realistic problem?
So, to trigger that __del__() method a second time, such an object would have to be:
1. Defined in the first place (the use cases for stateless objects with destructors seem rare...) 2. Hanging off a reference cycle 3. Which then gets resurrected
They don't need to hang off a reference cycle. You can resurrect a non-cyclic object from __del__ too. But, yeah, stateless objects must be pretty rare, since by definition they cannot represent anything (except perhaps "nothing").
i.e. force them to be GC-aware when they define a __del__ method, since they may still be hanging off the edge of a reference cycle, even if they can't form one themselves
Objects which hang off the edge of a reference cycle don't need to be GC-aware, since traversing them isn't needed to be break the cycle. I think "chalking it up as a CPython wart" is a reasonable solution, I just wanted to ask. Regards Antoine.
participants (3)
-
Antoine Pitrou
-
Benjamin Peterson
-
Nick Coghlan