[Zope-dev] ZPatterns: Errors in triggered methods + patch

Steve Alexander steve@cat-box.net
Wed, 12 Jul 2000 17:03:26 +0100


Latest ZPatterns release. Zope 2.2b4.

If I raise an error in an external method that is called by a
GenericTrigger, I sometimes get a strange log message:

2000-07-12T15:20:07 ERROR(200) ZODB Couldn't load state for
'\000\000\000\000\000\000\021='
Traceback (innermost last):
  File .../lib/python/ZODB/Connection.py, line 441, in setstate
  File .../lib/python/ZODB/FileStorage.py, line 584, in load
    (Object: .../var/Data.fs)
  File .../lib/python/ZODB/FileStorage.py, line 560, in _load
    (Object: .../var/Data.fs)
KeyError: p=

(Repeated four further times.)
(I replaced the path to my zope installation with "...".)

Sometimes, the characters after the "KeyError:" will be control
characters, and will cause further log output to look like gibberish,
until I suspend the Zope process and type "reset" at the xterm console.

I'm not sure why this happens. I've had another similar log message from
the same sort of cause:

2000-07-12T14:44:01 PANIC(300) ZODB A storage error occurred in the last
phase of a two-phase commit.  This shouldn't happen. The application may
be in a hosed state, so we will not allow transactions to commit from
here on
Traceback (innermost last):
  File .../lib/python/ZODB/Transaction.py, line 296, in commit
  File .../lib/python/Products/ZPatterns/Transactions.py, line 108, in
tpc_finish
  File .../lib/python/Products/ZPatterns/Transactions.py, line 135, in
end_tran
  File .../lib/python/Products/ZPatterns/DataManagers.py, line 118, in
_cleanup
    (Object: Transactional)
  File .../lib/python/ZODB/Connection.py, line 441, in setstate
  File .../lib/python/ZODB/FileStorage.py, line 584, in load
    (Object: .../var/Data.fs)
  File .../lib/python/ZODB/FileStorage.py, line 560, in _load
    (Object: .../var/Data.fs)
KeyError: p


I guess the methods that GenericTriggers call aren't supposed to throw
exceptions.

However, as a safeguard, how about changing the _checkpoint() method of
Agents.Agent to this:

    def _checkpoint(self):

        # Send 'final' versions of events

        try:
        
            for s,c,m in self._v_tranlog.values():
                try:
                    if s is ChangedStatus:
                        self._objectChanged(c,m)

                    elif s is AddedStatus:
                        self._objectAdded(c)

                    else:
                        self._objectDeleted(c,m)
                except:
                    import sys, traceback, string
                    type, val, tb = sys.exc_info()
                    sys.stderr.write(string.join( \
                        traceback.format_exception(type, val, tb),''))
                    del type, val,
tb                                                  
        finally:
            self._v_tranlog.clear()

I've put the call to each Agent's "change observed" event in a
try-except block. This makes my Zope instance happier when I do stupid
things in external methods, and has the additional advantage of
insulating other Agents from one particular Agent's problems.

--
Steve Alexander
Software Engineer
Cat-Box limited
http://www.cat-box.net