[Zope-dev] Double-aborting of objects registered w/transactions, and related weirdness related weirdness

Phillip J. Eby pje@telecommunity.com
Thu, 18 May 2000 17:05:40 -0500


[reported to Collector; posted as FYI]

Under certain circumstances, Zope transaction objects will have their
abort() method called more than once for the same transaction, which leads
to jar.abort() operations being called twice.  This occurs any time that
the zpublisher_exception_hook reraises the original exception, such as if
the exception is an 'unauthorized' or 'redirect', or if a
standard_error_message handler can't be found, or the transaction is being
executed by XML-RPC or some other non-HTML protocol.

Under "normal" circumstances (most other errors), the transaction's abort()
method is *still* called twice, but with different arguments that lead to
registered objects being aborted only once.

This is a mess, because to write objects which can be registered with a
transaction, one must consider the possibility of being aborted twice
during the same transaction.  It appears that the Zope exception hook uses
get_transaction.begin() in order to do an abort.  If it first did an
abort(), this would at least make the double-abort behavior consistent.  :)
 In practice, it seems as though it would be better to avoid double aborts
by always having the abort method clear/reset self._objects.  (The second
abort takes place as a result of the __del__ method being called while
there are still registered objects, following the free_transaction() called
in the first execution of abort().  (Are you confused yet?)

To add to the interestingness of this situation, there is a method which
releases cached connection objects associated with the transaction, in
collaboration with ZODB.DB.open().  This collaborating pair looks
completely broken, as it assumes only a single DB exists, and also the
method only ends up called by aborts, not commits.  It does not appear as
though anything in Zope uses this mechanism currently, but it should
probably be fixed or removed before somebody hurts themselves with it.  :)