zope.app.interface PersistentInterfaceClass dependents broken
Affects | Status | Importance | Assigned to | Milestone | ||
---|---|---|---|---|---|---|
Zope 3 | Status tracked in 3.4 | |||||
3.2 |
Fix Committed
|
Undecided
|
Unassigned | |||
3.3 |
Fix Committed
|
Undecided
|
Unassigned | |||
3.4 |
Fix Released
|
Medium
|
Unassigned |
Bug Description
zope.app.
the dependents attribute instead of the WeakKeyDictionary used in
zope.interface.
associated with this approach not exposed in any tests. Attached is a
diff to the tests of zope.app.interface and zope.app.component to
expose these bugs.
Firstly, if IFoo is a zope.app.
instance and zope.interface.
declaraion can't be verified from a different ZODB connection with
IFoo.providedBy
unpickle the dependents attribute of IFoo, it procedes down the
serialization of IFoo to the ProvidesClass instance representing the
declaration. It begins reconstituting the ProvidesClass instance,
which calls IFoo.subscribe(
attribute of IFoo. Since the ProvidesClass instance isn't persistent,
it has no oid the ZODB circular reference check doesn't catch this
circle. As a result the fix is to make sure that the declarations
instances in the dependents attribute are themselves persistent.
Also attached is a diff to zope.app.interface that replaces
PersistentInter
non-persistent declarations being added to the dependents attribute
into persistent versions of the same.
This fixes the problem but is not optimal because there are then two
instances for the same declaration, one in the ProvidesClass instance
stored in the object's __provides__ attribute and the other in the
dependents attribute of the PersistentInter
It seems like the more appropriate solution would be to check for
PersistentInter
zope.interface.
declaration classes for those declaraions. Since
PersistentInter
I wasn't sure which was the lesser of the two evils, so I restrained
my changes to zope.app. What might be a better solution? Give me
some feedback and I'll change the implementation.
There's another problem with the
zope.app.
zope.interface.
that declarations don't keep objects from being freed if the object is
removed. By using a PersistentDict for dependents, the declarations
can keep an object from being freed from memory and/or the ZODB when
the object is removed.
My first patch also includes tests for this bug. These tests seem to
have exposed another unrelated bug. An instance of a class that
subclasses persistent.
zope.interface.
instance and then the persistent object is added to the ZODB and
committed. Then if the persistent instance is deleted from the ZODB,
the transaction is committed, and the ZODB is packed, and gc.collect
is run, the ProvidesClass instance in the InterfaceClass instance
still remains. It does not, however, remain if the persistent
interface was never added to the ZODB.
I'm not sure if this represents a potential memory leak or not. What
confuses me is that it all behaves properly unless the persistent
instance is added to the ZODB. I noted the comment about weak
referrences being added to the ZODB optomistically in ZODB.serialize.
Could that be it? Unfortunately, my second patch doesn't include a
fix for this. I'd be happy to investigate this further if given a
little direction.
Uploaded: persistent- interfaces- fix.diff
a fix for all but the zope.interface. interface. InterfaceClass provides declaration weak reference bug