Source

hotdebug / hook_excpetion.py

#!/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(cb):
    '''
    Register a thread-local callback that will be called when THIS thread
    has uncaught exception
    '''
    _exception_callback_tls.cb = cb


def unregister_exception_callback():
    '''
    Reverse op of register_exception_callback
    '''
    if getattr(_exception_callback_tls, 'cb', None):
        del _exception_callback_tls.cb


def _hook_excpetion():

    def _wrap_dispatch(old):
        def dispatch(self, method, auth, params):
            try:
                return old(self, method, auth, params)
            except:
                cb = getattr(_exception_callback_tls, 'cb', None)
                # only process the same thread's exception
                if cb is not None:
                    cb(*sys.exc_info())
                raise
        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)


_hook_excpetion()
del _hook_excpetion