Comment 2 for bug 143917

Revision history for this message
Artur ZaprzaƂa (arturz) wrote :

I also hit this leak after upgrading from Zope-2.9.4 to Zope-2.11.1. The attachment contains a simple but working fix (I hope someone will create a more elegant solution).

Here is a sample PageTemplate that will trigger a memory leak:
<div tal:define="row python:context.some_Z_SQL_Method()[0]" tal:content="row/some_column"></div>

Someone willing to fix this bug will find this stack trace of evaluation of tal:content expression useful:
...
  Module zope.tales.expressions, line 217, in __call__
  Module Products.PageTemplates.Expressions, line 124, in _eval
  Module zope.tales.expressions, line 124, in _eval
  Module Products.PageTemplates.Expressions, line 79, in boboAwareZopeTraverse
  Module zope.interface.declarations, line 375, in implementedByFallback
...

Another example that leaks memory:
from zope.traversing.interfaces import ITraversable
ITraversable(row, None) # row is an instance of Shared.DC.ZRDB.Results.r

ITraversable instance is created somwhere on the way of evaluating tal:content="row/some_column" expression. As a consequence the class Shared.DC.ZRDB.Results.r gets registered somewhere in ZOPE inteface machinery which prevents garbage collector from freeing it and other referenced objects (like Shared.DC.ZRDB.Results.SQLAlias objects).

Tracking references using gc.get_referrers() I found that zope.interface.adapter.AdapterLookup instance keeps cache that looks like this:
{
<InterfaceClass zope.traversing.interfaces.ITraversable>: {
    <implementedBy Shared.DC.ZRDB.Results.r>: <class 'zope.traversing.adapters.DefaultTraversable'>,
    <implementedBy Shared.DC.ZRDB.Results.r>: <class 'zope.traversing.adapters.DefaultTraversable'>,
    <implementedBy Shared.DC.ZRDB.Results.r>: <class 'zope.traversing.adapters.DefaultTraversable'>,
    ...
    },
...
}

On my production machine this bug leaks almost 2GB of memory daily. The fix for the class Shared.DC.ZRDB.Results.r is the most urgent, but other on-the-fly created classes are also affected.