gc.garbage from paramiko

Andrew Bennetts andrew at canonical.com
Fri Feb 3 01:19:59 GMT 2006


When I run tests for some code I have here that uses bzr, the test runner (Zope
3's) warns me after each test that there's garbage in gc.garbage (i.e. cycles
that Python's garbage collector can't collect).  After the first test, it's
just:

[<paramiko.Transport at 0xB5DBD44CL (unconnected)>, <paramiko.Packetizer object at 0xb72d006c>, <paramiko.Transport at 0xB5D0672CL (unconnected)>, <paramiko.Packetizer object at 0xb5d0682c>] 

As the test suite runs, this accumulates, e.g:

[<paramiko.Transport at 0xB5DBD44CL (unconnected)>, <paramiko.Packetizer object at 0xb72d006c>, <paramiko.Transport at 0xB5D0672CL (unconnected)>, <paramiko.Packetizer object at 0xb5d0682c>, <paramiko.Transport at 0xB5D0CC4CL (unconnected)>, <paramiko.Packetizer object at 0xb5d0cdcc>, <paramiko.Transport at 0xB5DBD76CL (unconnected)>, <paramiko.Packetizer object at 0xb5d1306c>, <paramiko.Transport at 0xB5D1370CL (unconnected)>, <paramiko.Packetizer object at 0xb5d1394c>, <paramiko.Transport at 0xB5D1696CL (unconnected)>, <paramiko.Packetizer object at 0xb5d1688c>, <paramiko.Transport at 0xB5D1392CL (unconnected)>, <paramiko.Packetizer object at 0xb5d16d0c>, <paramiko.Transport at 0xB5D13F2CL (unconnected)>, <paramiko.Packetizer object at 0xb5d1bdec>, <paramiko.Transport at 0xB5D1BE0CL (unconnected)>, <paramiko.Packetizer object at 0xb5d1d20c>, <paramiko.Transport at 0xB5D1DFECL (unconnected)>, <paramiko.Packetizer object at 0xb5d1d1ac>, <paramiko.Transport at 0xB5D2372CL (unconnected)>, <paramiko.Packetizer object at 0xb5d2368c>]

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__.

I'm happy to help figure out alternative ways to achieve what paramiko uses
__del__ for, although, if I add the following monkey patch to my code, the
problem goes away (and all my tests keep passing):

    import paramiko
    del paramiko.Packetizer.__del__
    del paramiko.Transport.__del__

So I suspect using __del__ is not vitally important :)

The relevant part of my tests looks like:

    cmd_push().run_argv([remote_url])
    ...
    remote_branch = bzrlib.branch.Branch.open(remote_url)

    # Check that the pushed branch looks right
    self.assertEqual(
        self.local_branch.last_revision(), remote_branch.last_revision())

(it's testing a custom SFTP server)

I'm using jbailey's python2.4-paramiko 1.5.1-0ubuntu1.1 deb.

-Andrew.





More information about the bazaar mailing list