1"""Signals.py -- dump a python stacktrace if something bad happens.
2
3          DO NOT USE THIS MODULE IN PRODUCTION CODE
4
5This module has two functions in its public API:
6
7- dumpStackOnFatalSignal()
8  This function will install signal handlers that print a stacktrace and
9  then reraise the signal.
10
11- resetFatalSignals()
12  Restores the signal handlers to the state they had before the call to
13  dumpStackOnFatalSignal.
14
15This module is not designed to provide fine grained control over signal
16handling. Nor is it intended to be terribly robust. It may give useful
17information when your program gets unexpected signals, but it might just
18as easily cause a crash when such a signal gets in.
19
20          DO NOT USE THIS MODULE IN PRODUCTION CODE
21"""
22
23import signal
24import traceback
25import os
26
27__all__ = ["dumpStackOnFatalSignal", "resetFatalSignals"]
28
29originalHandlers = None
30
31def dumpHandler(signum, frame):
32    """
33    the signal handler used in this module: print a stacktrace and
34    then re-raise the signal
35    """
36    resetFatalSignals()
37    print "*** Handling fatal signal '%d'." % signum
38    traceback.print_stack(frame)
39    print "*** Restored handlers and resignaling."
40    os.kill(os.getpid(), signum)
41
42def installHandler(sig):
43    """
44    Install our signal handler for a signal. The original handler
45    is saved in 'originalHandlers'.
46    """
47    originalHandlers[sig] = signal.signal(sig, dumpHandler)
48
49def dumpStackOnFatalSignal():
50    """
51    Install signal handlers that might print a useful stack trace when
52    this process receives a fatal signal.
53
54    NOTE: See module docstring
55    """
56
57    global originalHandlers
58    if not originalHandlers:
59        originalHandlers = {}
60        installHandler(signal.SIGQUIT)
61        installHandler(signal.SIGILL)
62        installHandler(signal.SIGTRAP)
63        installHandler(signal.SIGABRT)
64        installHandler(signal.SIGEMT)
65        installHandler(signal.SIGFPE)
66        installHandler(signal.SIGBUS)
67        installHandler(signal.SIGSEGV)
68        installHandler(signal.SIGSYS)
69
70def resetFatalSignals():
71    """
72    Restore the original signal handlers
73    """
74    global originalHandlers
75    if originalHandlers:
76        for sig in originalHandlers:
77            signal.signal(sig, originalHandlers[sig])
78        originalHandlers = None
79