[New-bugs-announce] [issue17927] Argument copied into cell still referenced by frame

Guido van Rossum report at bugs.python.org
Tue May 7 18:02:23 CEST 2013


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 <report at bugs.python.org>
<http://bugs.python.org/issue17927>
_______________________________________


More information about the New-bugs-announce mailing list