[PATCH rfc] rfc: call gc at exit of mercurial

Pierre-Yves David pierre-yves.david at ens-lyon.org
Tue Apr 5 03:10:17 EDT 2016



On 04/04/2016 11:37 PM, Maciej Fijalkowski wrote:
> On Tue, Apr 5, 2016 at 8:36 AM, Pierre-Yves David
> <pierre-yves.david at ens-lyon.org> wrote:
>>
>>
>> On 04/04/2016 10:31 PM, Maciej Fijalkowski wrote:
>>>
>>> class A(object):
>>>       def __del__(self):
>>>           print "del"
>>>
>>> class B(object):
>>>       pass
>>>
>>> b = B()
>>> b.b = b
>>> b.a = A()
>>>
>>>
>>> This example does not call __del__ in CPython either.
>>>
>>> The __del__ is not guaranteed to be called - that's why there is a
>>> painful module finalization procedure where CPython is trying to call
>>> "as much as possible", but there are still no guarantees. If you add
>>> del b; gc.collect() you will see "del" printed. Of course this
>>> involves a cycle, but cycles can come in ways that you don't expect
>>> them and PyPy simply says "everything is GCed". I think it's very much
>>> in line with what python-dev thinks.
>>
>>
>> Which is why we have __del__ in very few object and we deploy massive effort
>> to ensure their don't get caught in cycle and mostly succeeding at this.
>> (Kind of the same we put a lot of effort into making sure __del__ are never
>> really called but keep them as double safety).
>>
>> So in the case we care about (no cycle) Cpython would call our __del__,
>> right?
>>
>> --
>> Pierre-Yves David
>
> Yes, but I would argue you can create cycles without knowing. E.g.
>
> def f():
>      try:
>         some_stuff
>      except:
>         x = sys.exc_info()
>
> creates a cycle. There are also ways to create cycles with passing
> global functions around etc.

<situation-summary>

Sure we can always makes more mistake (and we sometimes do). But in most 
of the rare case where __del__ catch one of this mistake, we don't have 
an extra mistake that prevent it from catching it! (Okay, I admit, I 
make this sentence extra confusing on purpose).

Simpler version (with cpython):
1) The official way is not to call __del__, we don't rely on it for well 
written code, (this kind of greg's point)
2) However, in rare case, the situation is extra buggy and __del__ is 
useful, (this is kind of my point),
3) However, in rare² care, the situation is extra² buggy and a cycle 
prevent __del__ to be called.

The bad new is that Pypy mostly remove (2), and make (3) replace most of 
it occurrence.

</situation-summary>

However, the good news is that we don't corrupt or loose anything in 
(2). We just leave the repo into an unrecovered state that people can 
recover with `hg recover`, so buggy code/situation expose slightly more 
anoying behavior. This is probably fine. (There might be some super old 
third party extension that will need to update itself).

someone should have a look at the other __del__ behavior and see if they 
have as "harmless" behavior (eg: lock.__del__ would leave the repository 
locked, but next run will remove that lock at the process is dead)

Cheers,

-- 
Pierre-Yves David


More information about the Mercurial-devel mailing list