[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