hotdebug /

Full commit
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: set ai et si ts=4 sts=4 sw=4:

import sys, threading

__all__ = ['register_exception_callback', 'unregister_exception_callback']

# thread-local storage for exception callback
_exception_callback_tls = threading.local()

def register_exception_callback(id, cb):
    Register a thread-local callback that will be called when THIS thread
    has uncaught exception
    if getattr(_exception_callback_tls, 'callbacks', None) is None:
        _exception_callback_tls.callbacks = {}
    _exception_callback_tls.callbacks[id] = cb

def unregister_exception_callback(id):
    Reverse op of register_exception_callback
    if getattr(_exception_callback_tls, 'callbacks', None):
        _exception_callback_tls.callbacks.pop(id, None)

def _hook_excpetion():

    def _wrap_dispatch(old):
        def dispatch(self, method, auth, params):
                return old(self, method, auth, params)
                cbs = getattr(_exception_callback_tls, 'callbacks', None)
                # only process the same thread's exception
                if cbs:
                    last_type, last_value, last_traceback = sys.exc_info()
                    for cb in cbs.itervalues():
                        cb(last_type, last_value, last_traceback)
        dispatch._hooked = True
        return dispatch

    from netsvc import ExportService
    for service in ExportService._services.itervalues():
        dispatch = service.__class__.__dict__.get('dispatch', None)
        if dispatch and getattr(dispatch, '_hooked', False):
            service.__class__.dispatch = _wrap_dispatch(dispatch)

del _hook_excpetion