On 02:31 am, ra...@twistedmatrix.com wrote:
On Fri, Jan 16, 2009 at 7:28 PM, Phil Christensen
<p...@bubblehouse.org> wrote:
Keeping references to tracebacks still has many potential pitfalls.
It's a fundamental problem: tracebacks refer to all their frames,
which refer to all their locals; this makes it *really* easy to create
uncollectable cycles if you have any __del__ methods *anywhere*. It's
just not safe to keep the traceback reference in the general case.
Failure needs to work with arbitrary code.
This used to be pretty much 100% of the time, since Deferred itself used
to have a __del__, so if you had a Deferred anywhere on the stack you
were dead. Nowadays it's a little better than that, but a surprising
number of objects from elsewhere are uncollectable.
Originally all __getstate__ did was stringify the object's state,
which is
probably why cleanFailure calls it directly. It looks to me like most
of the
code from __getstate__ should really be moved into a separate method,
which
would be called from cleanFailure as well as __getstate__.
Nevertheless cleanFailure will still need to remove the traceback, for
the reasons that Chris mentioned.
Sure, that would be a slightly better factoring.
Would that help, though?
I don't fully understand the issue, so this is probably wrong in some
obvious way, but: do we really need to hang on to a real traceback
object to resolve the issue in question? It sounds like the real issue
here is that we don't have a channel to communicate a "cleaned
traceback" (i.e., failure with stringified frames, but no traceback)
from one bit of code to another?
Note Beginning with Python 2.2, such cycles are automatically
reclaimed
when garbage collection is enabled and they become unreachable, but
it
remains more efficient to avoid creating cycles.
I'm not sure what Python documentation you're quoting here, but that's
not accurate in the general case. For example, see
<http://docs.python.org/library/gc.html#gc.garbage>:
"Objects that have __del__() methods and are part of a reference
cycle cause the entire reference cycle to be uncollectable".
I'd appreciate any feedback.
Two bits of feedback:
1. More of this discussion should be on a ticket. The mailing list is
good for getting discussions started and figuring out what needs to be
done, but now we're talking about the technical specifics of resolving a
specific problem. Someone (terry?) should take the specifics in the
email that started this thread and file an appropriate ticket.
2. When filing that ticket, I'd really like a full working example of
inlineCallbacks not showing a traceback to play with, not just examples
of portions of the problem. The obvious example I tried,
from twisted.internet.defer import inlineCallbacks
def buggy2():
raise RuntimeError("Whoops!")
@inlineCallbacks
def buggy():
yield buggy2()
buggy()
actually prints a nice descriptive traceback.
_______________________________________________
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python