gc.garbage from paramiko
Robey Pointer
robey at lag.net
Tue Feb 7 18:39:27 GMT 2006
I'm cc:ing the paramiko mailing list because I think this is relevant
there too.
On 6 Feb 2006, at 0:09, Andrew Bennetts wrote:
> On Fri, Feb 03, 2006 at 10:41:11AM -0800, Robey Pointer wrote:
>>
>> On 2 Feb 2006, at 17:19, Andrew Bennetts wrote:
>>
>>> The root cause is that paramiko is using __del__. This is almost
>>> always a bad
>>> idea, because objects with __del__ cannot be garbage collected if
>>> they're in a
>>> reference cycle. It's an almost certain way to cause memory leaks,
>>> unless
>>> you're *extremely* careful to always break cycles manually.
>>>
>>> I think paramiko should not use __del__.
>>
>> Unfortunately __del__ is needed for some python-file emulation, which
>> bzr and other apps rely on heavily, often without knowing (which is
>> the point). But it should be okay as long as no cycles are created.
>> But yes, I agree that use of __del__ is really a black art.
>
> What do you need to do on __del__? socket.sockets already close
> themselves just
> like files.
I guess that was kind of vague, sorry. :) Python borrows a concept
from c++, and causes files & sockets to auto-close themselves as soon
as the last reference goes away. Since paramiko supplies both socket-
like things (Channels) and file-like things (SFTPFiles), I've found
that python coders expect them to have the same del behavior as
builtins, allowing things like this:
open('email.txt', 'w').write('jdoe at example.com')
That said, I think the __del__ in Transport may be unnecessary. (I
don't think a Transport can be collected until all its channels are
already gone.) Though I'm still interested in cleaning up any
remaining cycles that get created, because after reading threads on
python-dev about this, I don't think the GC is going to be fixed
anytime soon.
> Cycles are really, really hard to avoid. If a traceback occurs,
> that can create
> cycles. There's lots of ways to unexpectedly make a cycle.
How could a traceback create a cycle?
> There's a pretty obvious cycle right here:
>
> self.packetizer.set_keepalive(interval,
> lambda x=self: x.global_request('keepalive at lag.net',
> wait=False))
Oops, yeah. Added to my to-do list. :) Although I don't think
that's the one you're seeing, because this code isn't called by bzr.
robey
More information about the bazaar
mailing list