/*1Interrupt and signal handling for Sage.23For documentation about how to use these, see the Developer's Guide.45This code distinguishes between two kinds of signals:67(1) interrupt-like signals: SIGINT, SIGALRM, SIGHUP. The word8"interrupt" refers to any of these signals. These need not be handled9immediately, we might handle them at a suitable later time, outside of10sig_block() and with the Python GIL acquired. SIGINT raises a11KeyboardInterrupt (as usual in Python), SIGALRM raises AlarmInterrupt12(a custom exception inheriting from KeyboardInterrupt), while SIGHUP13raises SystemExit, causing Python to exit. The latter signal also14redirects stdin from /dev/null, to cause interactive sessions to exit.1516(2) critical signals: SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGBUS, SIGSEGV.17These are critical because they cannot be ignored. If they happen18outside of sig_on(), we can only exit Sage with the dreaded19"unhandled SIG..." message. Inside of sig_on(), they can be handled20and raise various exceptions (see sage/ext/c_lib.pyx). SIGQUIT will21never be handled and always causes Sage to exit.222324AUTHORS:2526- William Stein, Martin Albrecht (2006): initial version2728- Jeroen Demeyer (2010-10-03): almost complete rewrite (#9678)2930- Jeroen Demeyer (2013-01-11): handle SIGHUP also (#13908)3132- Jeroen Demeyer (2013-01-28): handle SIGQUIT also (#14029)3334- Jeroen Demeyer (2013-05-13): handle SIGALRM also (#13311)3536*/3738/*****************************************************************************39* Copyright (C) 2006 William Stein <[email protected]>40* 2006 Martin Albrecht <[email protected]>41* 2010-2013 Jeroen Demeyer <[email protected]>42*43* Distributed under the terms of the GNU General Public License (GPL)44* as published by the Free Software Foundation; either version 2 of45* the License, or (at your option) any later version.46* http://www.gnu.org/licenses/47****************************************************************************/4849/* Whether or not to compile debug routines for the interrupt handling50* code (0: disable, 1: enable). Enabling will make the code slower.51* The debug level itself needs to be set in c_lib/src/interrupt.c */52#define ENABLE_DEBUG_INTERRUPT 0535455#ifndef C_LIB_INCLUDE_INTERRUPT_H56#define C_LIB_INCLUDE_INTERRUPT_H57#include <Python.h>58#include <setjmp.h>59#include <signal.h>6061#ifdef __cplusplus62extern "C" {63#endif646566/* Declare likely() and unlikely() as in Cython */67#ifdef __GNUC__68/* Test for GCC > 2.95 */69#if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))70#define HAVE_BUILTIN_EXPECT 171#endif72#endif7374#if HAVE_BUILTIN_EXPECT75#define likely(x) __builtin_expect(!!(x), 1)76#define unlikely(x) __builtin_expect(!!(x), 0)77#else78#define likely(x) (x)79#define unlikely(x) (x)80#endif8182/* Interrupt debug level */83#if ENABLE_DEBUG_INTERRUPT84extern int sage_interrupt_debug_level;85#endif868788/* Print a C backtrace if supported by libc */89void print_backtrace(void);9091/* Print a message s and kill ourselves with signal sig */92void sigdie(int sig, const char* s);939495/*96* The signal handlers for Sage, one for interrupt-like signals97* (SIGINT, SIGHUP) and one for critical signals like SIGSEGV.98*99* Inside sig_on() (i.e. when _signals.sig_on_count is positive), these100* handlers raise an exception and jump back to sig_on().101* Outside of sig_on(), sage_interrupt_handler() sets Python's102* interrupt flag using PyErr_SetInterrupt(); sage_signal_handler()103* terminates Sage.104*/105void sage_interrupt_handler(int sig);106void sage_signal_handler(int sig);107108/*109* Setup the signal handlers. It is safe to call this more than once.110*111* We do not handle SIGALRM since there is code to deal with112* alarms in sage/misc/misc.py113*/114void setup_sage_signal_handler(void);115116117/**********************************************************************118* SAGE_SIGNALS_T STRUCTURE *119**********************************************************************/120121/* All the state of the signal handler is in this struct. */122struct sage_signals_t123{124/* Reference counter for sig_on().125* If this is strictly positive, we are inside a sig_on(). */126volatile sig_atomic_t sig_on_count;127128/* If this is nonzero, it is a signal number of a non-critical129* signal (e.g. SIGINT) which happened during a time when it could130* not be handled. This may be set when an interrupt occurs either131* outside of sig_on() or inside sig_block(). To avoid race132* conditions, this value may only be changed when all133* interrupt-like signals are masked. */134volatile sig_atomic_t interrupt_received;135136/* Are we currently handling a signal inside sage_signal_handler()?137* This is set to 1 on entry in sage_signal_handler (not in138* sage_interrupt_handler) and 0 in _sig_on_postjmp. This is139* needed to check for signals raised within the signal handler. */140volatile sig_atomic_t inside_signal_handler;141142/* Non-zero if we currently are in a function such as malloc()143* which blocks interrupts, zero normally.144* See sig_block(), sig_unblock(). */145volatile sig_atomic_t block_sigint;146147/* A jump buffer holding where to siglongjmp() after a signal has148* been received. This is set by sig_on(). */149sigjmp_buf env;150151/* External Cython function which actually raises the appropriate152* exception depending on the signal number. Must be set153* immediately after calling setup_sage_signal_handler(). */154int (*raise_exception)(int sig, const char* msg);155156/* An optional string may be passed to the signal handler which157* will be used as the text for the exception. This can be set158* using sig_str() instead of sig_on() or it can be changed by159* set_sage_signal_handler_message() declared below.160*/161const char* s;162};163164/*165* The actual object (there is a unique copy of this throughout Sage).166*/167extern struct sage_signals_t _signals;168169170/**********************************************************************171* IMPLEMENTATION OF SIG_ON/SIG_OFF *172**********************************************************************/173174/*175* Implementation of sig_on(). Applications should not use this176* directly, use sig_on() or sig_str() instead.177*178* _sig_on_(message) is a macro which pretends to be a function.179* Since this is declared as "cdef except 0", Cython will know that an180* exception occured if the value of _sig_on_() is 0 (false).181*182* INPUT:183*184* - message -- a string to be displayed as error message when the code185* between sig_on() and sig_off() fails and raises an exception.186*187* OUTPUT: zero if an exception occured, non-zero otherwise.188*189* The function sigsetjmp() in the _sig_on_() macro can return:190* - zero: this happens in the actual sig_on() call. sigsetjmp() sets191* up the address for the Sage signal handler to jump to. The192* program continues normally.193* - a signal number (e.g. 2 for SIGINT), assumed to be strictly194* positive: the Sage signal handler handled a signal. Since195* _sig_on_() will return 0 in this case, the Exception (raised by196* sage_signal_handler) will be detected by Cython.197* - a negative number: this is assumed to come from sig_retry(). In198* this case, the program continues as if nothing happened between199* sig_on() and sig_retry().200*201* We cannot simply put sigsetjmp() in a function, because when that202* function returns, we would lose the stack frame to siglongjmp() to.203* That's why we need this hackish macro. We use the fact that || is204* a short-circuiting operator (the second argument is only evaluated205* if the first returns 0).206*/207#define _sig_on_(message) ( unlikely(_sig_on_prejmp(message, __FILE__, __LINE__)) || _sig_on_postjmp(sigsetjmp(_signals.env,0)) )208209/* This will be called during _sig_on_postjmp() when an interrupt was210* received *before* the call to sig_on(). */211void _sig_on_interrupt_received(void);212213/*214* Set message, return 0 if we need to sigsetjmp(), return 1 otherwise.215*/216static inline int _sig_on_prejmp(const char* message, const char* file, int line)217{218_signals.s = message;219#if ENABLE_DEBUG_INTERRUPT220if (sage_interrupt_debug_level >= 4)221{222fprintf(stderr, "sig_on (count = %i) at %s:%i\n", _signals.sig_on_count+1, file, line);223fflush(stderr);224}225#endif226if (_signals.sig_on_count > 0)227{228_signals.sig_on_count++;229return 1;230}231232/* At this point, _signals.sig_on_count == 0 */233return 0;234}235236237/* Cleanup after siglongjmp() (reset signal mask to the default, set238* sig_on_count to zero) */239void _sig_on_recover(void);240241/*242* Process the return value of sigsetjmp().243* Return 0 if there was an exception, 1 otherwise.244*/245static inline int _sig_on_postjmp(int jmpret)246{247if (unlikely(jmpret > 0))248{249/* An exception occured */250_sig_on_recover();251return 0;252}253254/* When we are here, it's either the original sig_on() call or we255* got here after sig_retry(). */256_signals.sig_on_count = 1;257258/* Check whether we received an interrupt before this point.259* _signals.interrupt_received can only be set by the interrupt260* handler if _signals.sig_on_count is zero. Because of that and261* because _signals.sig_on_count and _signals.interrupt_received are262* volatile, we can safely evaluate _signals.interrupt_received here263* without race conditions. */264if (unlikely(_signals.interrupt_received))265{266_sig_on_interrupt_received();267return 0;268}269270return 1;271}272273/* Give a warning that sig_off() was called without sig_on() */274void _sig_off_warning(const char* file, int line);275276/*277* Implementation of sig_off(). Applications should not use this278* directly, use sig_off() instead.279*/280static inline void _sig_off_(const char* file, int line)281{282#if ENABLE_DEBUG_INTERRUPT283if (sage_interrupt_debug_level >= 4)284{285fprintf(stderr, "sig_off (count = %i) at %s:%i\n", _signals.sig_on_count, file, line);286fflush(stderr);287}288#endif289if (unlikely(_signals.sig_on_count <= 0))290{291_sig_off_warning(file, line);292}293else294{295--_signals.sig_on_count;296}297}298299300/**********************************************************************301* USER MACROS/FUNCTIONS *302**********************************************************************/303304/* The actual macros which should be used in a program. */305#define sig_on() _sig_on_(NULL)306#define sig_str(message) _sig_on_(message)307#define sig_off() _sig_off_(__FILE__, __LINE__)308309/* sig_check() should be functionally equivalent to sig_on(); sig_off();310* but much faster. Essentially, it checks whether we missed any311* interrupts.312*313* OUTPUT: zero if an interrupt occured, non-zero otherwise.314*/315static inline int sig_check()316{317if (unlikely(_signals.interrupt_received) && _signals.sig_on_count == 0)318{319_sig_on_interrupt_received();320return 0;321}322323return 1;324}325326/* Macros behaving exactly like sig_on, sig_str and sig_check327* but which are *not* declared cdef except 0. This is useful if some328* Cython code wants to do its own exception handling. */329#define sig_on_no_except() sig_on()330#define sig_str_no_except(message) sig_str(message)331#define sig_check_no_except() sig_check()332333334/*335* Temporarily block interrupts from happening inside sig_on(). This336* is meant to wrap malloc() for example. sig_unblock() checks whether337* an interrupt happened in the mean time. If yes, the interrupt is338* re-raised.339*340* NOTES:341* - This only works inside sig_on()/sig_off(). Outside of sig_on(),342* interrupts behave as usual. This is because we can't propagate343* Python exceptions from low-level C code.344* - Other signals still go through, because we can't really ignore345* SIGSEGV for example.346* - For efficiency reasons, currently these may NOT be nested.347* Nesting could be implemented like src/headers/pariinl.h in PARI.348*/349static inline void sig_block()350{351#if ENABLE_DEBUG_INTERRUPT352if (_signals.block_sigint != 0)353{354fprintf(stderr, "\n*** WARNING *** sig_block() with sig_on_count = %i, block_sigint = %i\n", _signals.sig_on_count, _signals.block_sigint);355print_backtrace();356}357#endif358_signals.block_sigint = 1;359}360361static inline void sig_unblock()362{363#if ENABLE_DEBUG_INTERRUPT364if (_signals.block_sigint != 1)365{366fprintf(stderr, "\n*** WARNING *** sig_unblock() with sig_on_count = %i, block_sigint = %i\n", _signals.sig_on_count, _signals.block_sigint);367print_backtrace();368}369#endif370_signals.block_sigint = 0;371372if (unlikely(_signals.interrupt_received) && _signals.sig_on_count > 0)373kill(getpid(), _signals.interrupt_received); /* Re-raise the signal */374}375376377/*378* Call this before raising an exception to set _signals.s. The string379* s will be used as the text for the exception. Note that s is not380* copied, we just store the pointer.381*/382void set_sage_signal_handler_message(const char* s);383384385/*386* Retry a failed computation starting from sig_on(). This is useful387* for PARI: if PARI complains that it doesn't have enough memory, we388* allocate a larger stack and retry the computation.389*/390static inline void sig_retry()391{392/* If we're outside of sig_on(), we can't jump, so we can only bail393* out */394if (unlikely(_signals.sig_on_count <= 0))395{396fprintf(stderr, "sig_retry() without sig_on()\n");397abort();398}399siglongjmp(_signals.env, -1);400}401402/* Used in error callbacks from C code (in particular NTL and PARI).403* This should be used after an exception has been raised to jump back404* to sig_on() where the exception will be seen. */405static inline void sig_error()406{407if (unlikely(_signals.sig_on_count <= 0))408{409fprintf(stderr, "sig_error() without sig_on()\n");410}411abort();412}413414415/*416* This function does nothing, but it is declared cdef except *, so it417* can be used to make Cython check whether there is a pending exception418* (PyErr_Occurred() is non-NULL).419* To Cython, it will look like cython_check_exception() actually420* raised the exception.421*/422static inline void cython_check_exception() {return;}423424425#ifdef __cplusplus426} /* extern "C" */427#endif428#endif /* C_LIB_INCLUDE_INTERRUPT_H */429430431