New submission from Guido van Rossum:

This came out of some investigations into Tulip reference cycles.  I've only 
confirmed this with 3.3 and 3.4, but I suspect it's a problem in earlier 
versions too.

The scenario is as follows.

Consider a object with a method that ends up catching an exception and storing 
the exception on the object.  We know that the __traceback__ attribute of the 
exception references the stack frame where the exception was caught, so there 
is a cycle: self -> exception -> traceback -> frame -> self.  To break this 
cycle without disturbing the __traceback__ on the exception, the method sets 
"self = None" before it returns.  (The point of breaking the cycle is that at 
some later point when the object is deleted the traceback can be printed by the 
__del__ method.)

This works beautifully...  Except if the function happens to contain a nested 
function or a lambda that references 'self'.  *Even if the function is never 
created* (e.g. "if 0: lambda: self").  Then setting "self = None" does not 
break the cycle.  It's not a real leak, because gc.collect() will collect the 
cycle.  But it's still annoying that I can't break the cycle (I don't want to 
break it at any other point because it would reduce the usefulness of the 
exception stored on the object).

After two days of investigations and thinking about it I found the cause: the 
presence of the lambda cause a cell to be created into which self is copied, 
but the original self argument is still referenced by the frame.  Setting "self 
= None" clears the cell but doesn't affect the original self argument.  (FWIW, 
this indicates it's not specifically about self, it's about any argument that 
gets copied into a cell.)

I thought I had a one-line fix (see cellfree.diff attached) but it breaks 
argument-less super(), which looks at the original first argument.  I think I 
can fix super() (it must introspect the code object to find out into which cell 
self has been copied, if it finds it NULL), but I have to think about that 
more.  If anyone wants to jump in and suggest an approach to that I'd 
appreciate it.

----------
assignee: gvanrossum
components: Interpreter Core
files: cellfree.diff
keywords: patch
messages: 188672
nosy: gvanrossum
priority: normal
severity: normal
stage: needs patch
status: open
title: Argument copied into cell still referenced by frame
type: resource usage
versions: Python 3.3
Added file: http://bugs.python.org/file30166/cellfree.diff

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue17927>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to