Ticket #9678: 9678.patch

File 9678.patch, 43.4 KB (added by jdemeyer, 9 years ago)
  • c_lib/include/interrupt.h

    # HG changeset patch
    # User Jeroen Demeyer <jdemeyer@cage.ugent.be>
    # Date 1287748872 -7200
    # Node ID 875182787c8abb814cdcf73c944c499af882baac
    # Parent  2022ce865df280ae9d89335e2af3ca0bdabacba7
    #9678: Rewrite interrupt handling
    
    diff -r 2022ce865df2 -r 875182787c8a c_lib/include/interrupt.h
    a b  
    1 /******************************************************************************
    2        Copyright (C) 2006 William Stein <wstein@gmail.com>
    3                      2006 Martin Albrecht <malb@informatik.uni-bremen.de>
     1/*
     2Interrupt and signal handling for Sage.
    43
    5   Distributed under the terms of the GNU General Public License (GPL), Version 2.
     4For documentation about how to use these, see the Developer's Guide.
    65
    7   The full text of the GPL is available at:
    8                   http://www.gnu.org/licenses/
    96
    10 ******************************************************************************/
     7AUTHORS:
     8
     9- William Stein, Martin Albrecht (2006): initial version
     10
     11- Jeroen Demeyer (2010-10-03): almost complete rewrite (#9678)
     12
     13*/
     14
     15/*****************************************************************************
     16 *       Copyright (C) 2006 William Stein <wstein@gmail.com>
     17 *                     2006 Martin Albrecht <malb@informatik.uni-bremen.de>
     18 *                     2010 Jeroen Demeyer <jdemeyer@cage.ugent.be>
     19 *
     20 *  Distributed under the terms of the GNU General Public License (GPL)
     21 *  as published by the Free Software Foundation; either version 2 of
     22 *  the License, or (at your option) any later version.
     23 *                  http://www.gnu.org/licenses/
     24 ****************************************************************************/
     25
     26/* Whether or not to enable interrupt debugging (0: disable, 1: enable) */
     27#define ENABLE_DEBUG_INTERRUPT 0
     28
    1129
    1230#ifndef C_LIB_INCLUDE_INTERRUPT_H
    1331#define C_LIB_INCLUDE_INTERRUPT_H
     32#include <Python.h>
    1433#include <setjmp.h>
    15 #include <Python.h>
    1634#include <signal.h>
    1735
     36#ifdef __cplusplus
     37extern "C" {
     38#endif
    1839
    1940
    20 /* In your Cython code, put
    21 
    22     sig_on()
    23     [pure c code block]
    24     sig_off()
    25 
    26    to get signal handling capabilities.
    27 
    28    VERY VERY IMPORTANT: 
    29        1. These *must* always come in pairs. E.g., if you have just
    30           a sig_off() without a corresponding sig_on(), then ctrl-c
    31           later in the interpreter will segfault!
    32 
    33        2. Do *not* put these in the __init__ method of a Cython extension
    34           class, or you'll get crashes.
    35 
    36        3. Do not put these around any non-pure C code!!!!
    37 
    38 
    39 
    40 
    41 */
    42 
    43 /**
    44  * bitmask to enable the sage signal handler
    45  */
    46 
    47 #define SIG_SAGE_HANDLER 1
    48 
    49 /**
    50  * bitmask to enable long jumps
    51  */
    52 #define SIG_LONG_JMP 2
    53 
    54 /**
    55  * bitmask that a signal has been received.
    56  *
    57  */
    58 
    59 #define SIG_SIGNAL_RECEIVED 4
    60 
    61 /**
    62  * default signal handler for SIGINT, SIGALRM, SIGSEGV, SIGABRT,
    63  * SIGFPE in the context of SAGE. It calls the default Python handler
    64  * if _signals.sage_handler == 0.
    65  */
    66 
    67 void sage_signal_handler(int n);
    68 
    69 
    70 /**
    71  * fallback signal handlers
    72  */
    73 void sig_handle_sigsegv(int n);
    74 void sig_handle_sigbus(int n);
    75 void sig_handle_sigfpe(int n);
    76 
    77 /**
    78  * Supposed to be called exactly once to ensure the SAGE signal
    79  * handler is the default signal handler. This function implements a
    80  * mechanism to make sure it is only called once so it is safe to call
    81  * it more than once.
    82  *
    83  */
    84 
    85 void setup_signal_handler(void);
    86 
    87 #if defined (__sun__) || defined (__sun)   /* Needed for Solaris below. */
    88    typedef void (*__sighandler_t )();
     41/* Declare likely() and unlikely() as in Cython */
     42#ifdef __GNUC__
     43/* Test for GCC > 2.95 */
     44#if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
     45#define HAVE_BUILTIN_EXPECT 1
     46#endif
    8947#endif
    9048
    91 /**
    92  * All relevant data for the signal handler is bundled in this struct.
    93  *
    94  */
    95 
    96 struct sage_signals {
    97 
    98   /**
    99    * Bitmask which determines what to do in the signal handler. Let
    100    * bit 0 be the least significant bit, then the bitmask is as follows:
    101    \verbatim
    102      bit | semantic
    103      -------------------------------------------
    104        0 | use sage signal handler (1) or default (0)
    105        1 | use longjmp (1) or return (0)
    106        2 | signal received (1) or not (0)
    107    \endverbatim
    108    *
    109    * You may want to use the provided definitions SIG_SAGE_HANDLER,
    110    * SIG_LONG_JMP, SIG_SIGNAL_RECEIVED.
    111    */
    112 
    113   int mpio;
    114 
    115   /**
    116    * An internal buffer holding where to jump after a signal has been
    117    * received, don't touch!
    118    */
    119 
    120   sigjmp_buf env;
    121 
    122 
    123   /**
    124    * An optional string may be passed to the signal handler which will
    125    * be printed. Use sig_str() for that.
    126    */
    127   char *s;
    128  
    129 
    130   /**
    131    * Unfortunately signal handler function declarations vary HUGELY
    132    * from platform to platform:
    133    */
    134 
    135 #if defined(__CYGWIN32__)     /* Windows XP */
    136 
    137   _sig_func_ptr  python_handler;
    138 
    139 #elif defined(__FreeBSD__)    /* FreeBSD */
    140 
    141   sig_t  python_handler;
    142 
    143 #elif defined(__APPLE__)      /* OSX */
    144 
    145   sig_t  python_handler;
    146 
    147 #elif defined (__sun__) || defined (__sun)   /* Solaris */
    148 
    149   __sighandler_t  python_handler;
    150 
    151 #else                                   /* Other, e.g., Linux */
    152 
    153   __sighandler_t python_handler;
    154 
     49#if HAVE_BUILTIN_EXPECT
     50#define likely(x)   __builtin_expect(!!(x), 1)
     51#define unlikely(x) __builtin_expect(!!(x), 0)
     52#else
     53#define likely(x)   (x)
     54#define unlikely(x) (x)
    15555#endif
    15656
     57
     58
     59/* Print a C backtrace if supported by libc */
     60void print_backtrace(void);
     61
     62/* Print a message s and kill ourselves with signal sig */
     63void sigdie(int sig, const char* s);
     64
     65
     66/*
     67 * The signal handlers for Sage, one for SIGINT and one for other
     68 * signals.
     69 * Inside sig_on() (i.e. when _signals.sig_on_count is positive), this
     70 * raises an exception and jumps back to sig_on().
     71 * Outside of sig_on(), sage_interrupt_handler() sets Python's
     72 * interrupt flag using PyErr_SetInterrupt(); sage_signal_handler()
     73 * terminates Sage.
     74 */
     75void sage_interrupt_handler(int sig);    /* SIGINT */
     76void sage_signal_handler(int sig);       /* Other signals */
     77
     78/* Wrapper to call sage_interrupt_handler() "by hand". */
     79void call_sage_interrupt_handler(int sig);
     80
     81/*
     82 * Setup the signal handlers for SIGINT, SIGILL, SIGABRT, SIGFPE
     83 * SIGBUS, SIGSEGV. It is safe to call this more than once.
     84 *
     85 * We do not handle SIGALRM since there is code to deal with
     86 * alarms in sage/misc/misc.py
     87 */
     88void setup_sage_signal_handler(void);
     89
     90
     91/**********************************************************************
     92 * SAGE_SIGNALS_T STRUCTURE                                           *
     93 **********************************************************************/
     94
     95/* All the state of the signal handler is in this struct. */
     96struct sage_signals_t
     97{
     98    /* Reference counter for sig_on().
     99     * If this is strictly positive, we are inside a sig_on(). */
     100    volatile sig_atomic_t sig_on_count;
     101
     102    /* If this is nonzero, check for interrupts using PyErr_Occured()
     103     * during sig_on() and sig_unblock(). This value is increased
     104     * whenever an interrupt happens outside of sig_on() or inside
     105     * sig_block(). */
     106    volatile sig_atomic_t interrupt_received;
     107
     108    /* Are we currently handling a signal inside sage_signal_handler()?
     109     * This is set to 1 on entry in sage_signal_handler (not in
     110     * sage_interrupt_handler) and 0 in _sig_on_postjmp.  This is
     111     * needed to check for signals raised within the signal handler. */
     112    volatile sig_atomic_t inside_signal_handler;
     113
     114    /* Non-zero if we currently are in a function which blocks SIGINT,
     115     * zero normally.  See sig_block(), sig_unblock(). */
     116    volatile sig_atomic_t block_sigint;
     117
     118    /* A jump buffer holding where to siglongjmp() after a signal has
     119     * been received. This is set by sig_on(). */
     120    sigjmp_buf env;
     121
     122    /* An optional string may be passed to the signal handler which
     123     * will be used as the text for the exception. This can be set
     124     * using sig_str() instead of sig_on() or it can be changed by
     125     * set_sage_signal_handler_message() declared below.
     126     */
     127    const char* s;
    157128};
    158129
    159 /**
    160  * The actual object.
     130/*
     131 * The actual object (there is a unique copy of this throughout Sage).
    161132 */
     133extern struct sage_signals_t _signals;
    162134
    163 extern struct sage_signals _signals;
    164135
    165 /**
    166  * Enables SAGE signal handling for the following C block. This macro
    167  * *MUST* be followed by sig_off().
    168  *
    169  *
    170  * See also @ref sig_str()
    171  */
    172 
    173 #define sig_on() if (_signals.mpio == 0) { _signals.mpio = 1+2; _signals.s = NULL;\
    174                  if (sigsetjmp(_signals.env,1)) { \
    175                   _signals.mpio = 0;   \
    176                   return(0); \
    177                 } } // else { _signals.s = "Unbalanced sig_on()/sig_off()\n"; fprintf(stderr, _signals.s); sage_signal_handler(SIGABRT); }
    178 
    179 /* /\** */
    180 /*  * Enables SAGE signal handling for the following C block. This macro */
    181 /*  * *MUST* be followed by _sig_off_short. */
    182 /*  * */
    183 /*  * If the following block takes very little time to compute this macro */
    184 /*  * is the right choice. Otherwise sig_on() is appropriate. */
    185 /*  * */
    186 /*  * See also sig_on() and sig_str(). */
    187 /*  * */
    188 /*  *\/ */
    189 
    190 /* #define _sig_on_short _signals.mpio = 1 */
    191 
    192 
    193 /**
    194  * Same as @ref sig_on() but with string support
    195  *
    196  */
    197  
    198 #define sig_str(mstring) if (_signals.mpio == 0) { _signals.mpio = 1+2; \
    199                 _signals.s = mstring; \
    200                 if (sigsetjmp(_signals.env,1)) { \
    201                   _signals.mpio = 0; \
    202                  return(0); \
    203                 } } //else { _signals.s = "Unbalanced sig_str()/sig_off()\n"; fprintf(stderr, _signals.s); sage_signal_handler(SIGABRT); }
    204 
     136/**********************************************************************
     137 * IMPLEMENTATION OF SIG_ON/SIG_OFF                                   *
     138 **********************************************************************/
    205139
    206140/*
    207   This function may be called by the code that *raises* the signal (before raising
    208   the signal) to pass an error message back to the handler (for example to appear as the
    209   text accompanying the python RuntimeError exception) 
     141 * Implementation of sig_on().  Applications should not use this
     142 * directly, use sig_on() or sig_str() instead.
     143 *
     144 * _sig_on_(message) is a macro which pretends to be a function.
     145 * Since this is declared as "cdef except 0", Cython will know that an
     146 * exception occured if the value of _sig_on_() is 0 (false).
     147 *
     148 * INPUT:
     149 *
     150 *  - message -- a string to be displayed as error message when the code
     151 *    between sig_on() and sig_off() fails and raises an exception.
     152 *
     153 * OUTPUT: zero if an exception occured, non-zero otherwise.
     154 *
     155 * The function sigsetjmp() in the _sig_on_() macro can return:
     156 *  - zero: this happens in the actual sig_on() call. sigsetjmp() sets
     157 *    up the address for the Sage signal handler to jump to.  The
     158 *    program continues normally.
     159 *  - a signal number (e.g. 2 for SIGINT), assumed to be strictly
     160 *    positive: the Sage signal handler handled a signal.  Since
     161 *    _sig_on_() will return 0 in this case, the Exception (raised by
     162 *    sage_signal_handler) will be detected by Cython.
     163 *  - a negative number: this is assumed to come from sig_retry().  In
     164 *    this case, the program continues as if nothing happened between
     165 *    sig_on() and sig_retry().
     166 *
     167 * We cannot simply put sigsetjmp() in a function, because when that
     168 * function returns, we would lose the stack frame to siglongjmp() to.
     169 * That's why we need this hackish macro.  We use the fact that || is
     170 * a short-circuiting operator (the second argument is only evaluated
     171 * if the first returns 0).
     172 */
     173#define _sig_on_(message) ( unlikely(_sig_on_prejmp(message, __FILE__, __LINE__)) || _sig_on_postjmp(sigsetjmp(_signals.env,0)) )
     174
     175/* This will be called during _sig_on_postjmp() when a SIGINT was
     176 * received *before* the call to sig_on().
     177 * Return 0 if there was an interrupt, 1 otherwise. */
     178int _sig_on_interrupt_received(void);
     179
     180/*
     181 * Set message, return 0 if we need to sigsetjmp(), return 1 otherwise.
     182 */
     183static inline int _sig_on_prejmp(const char* message, const char* file, int line)
     184{
     185    _signals.s = message;
     186#if ENABLE_DEBUG_INTERRUPT
     187    fprintf(stderr, "sig_on (counter = %i) at %s:%i\n", _signals.sig_on_count+1, file, line);
     188    fflush(stderr);
     189#endif
     190    if (_signals.sig_on_count > 0)
     191    {
     192        _signals.sig_on_count++;
     193        return 1;
     194    }
     195
     196    /* At this point, _signals.sig_on_count == 0 */
     197    return 0;
     198}
     199
     200
     201/* Cleanup after siglongjmp() (reset signal mask to the default, set
     202 * sig_on_count to zero) */
     203void _sig_on_recover(void);
     204
     205/*
     206 * Process the return value of sigsetjmp().
     207 * Return 0 if there was an exception, 1 otherwise.
     208 */
     209static inline int _sig_on_postjmp(int jmpret)
     210{
     211    if (unlikely(jmpret > 0))
     212    {
     213        /* An exception occured */
     214        _sig_on_recover();
     215        return 0;
     216    }
     217
     218    /* When we are here, it's either the original sig_on() call or we
     219     * got here after sig_retry(). */
     220    _signals.sig_on_count = 1;
     221
     222    /* Check whether we received an interrupt before this point.
     223     * _signals.interrupt_received can only be set by the interrupt
     224     * handler if _signals.sig_on_count is zero.  Because of that and
     225     * because _signals.sig_on_count and _signals.interrupt_received are
     226     * volatile, we can safely evaluate _signals.interrupt_received here
     227     * without race conditions. */
     228    if (unlikely(_signals.interrupt_received))
     229        return _sig_on_interrupt_received();
     230
     231    return 1;
     232}
     233
     234/* Give a warning that sig_off() was called without sig_on() */
     235void _sig_off_warning(const char* file, int line);
     236
     237/*
     238 * Implementation of sig_off().  Applications should not use this
     239 * directly, use sig_off() instead.
     240 */
     241static inline void _sig_off_(const char* file, int line)
     242{
     243#if ENABLE_DEBUG_INTERRUPT
     244    fprintf(stderr, "sig_off (counter = %i) at %s:%i\n", _signals.sig_on_count, file, line);
     245    fflush(stderr);
     246#endif
     247    if (unlikely(_signals.sig_on_count <= 0))
     248    {
     249        _sig_off_warning(file, line);
     250    }
     251    else
     252    {
     253        --_signals.sig_on_count;
     254    }
     255}
     256
     257
     258
     259/**********************************************************************
     260 * USER MACROS/FUNCTIONS                                              *
     261 **********************************************************************/
     262
     263/* The actual macros which should be used in a program. */
     264#define sig_on()           _sig_on_(NULL)
     265#define sig_str(message)   _sig_on_(message)
     266#define sig_off()          _sig_off_(__FILE__, __LINE__)
     267
     268/* These deprecated macros provide backwards compatibility with
     269 * sage-4.6 and earlier */
     270#define _sig_on        {if (!_sig_on_(NULL)) return 0;}
     271#define _sig_str(s)    {if (!_sig_on_(s)) return 0;}
     272#define _sig_off       {_sig_off_(__FILE__, __LINE__);}
     273
     274
     275/* sig_check() should be functionally equivalent to sig_on(); sig_off();
     276 * but much faster.  Essentially, it checks whether we missed any
     277 * interrupts.
     278 *
     279 * OUTPUT: zero if an interrupt occured, non-zero otherwise.
     280 */
     281static inline int sig_check()
     282{
     283    if (unlikely(_signals.interrupt_received) && _signals.sig_on_count == 0)
     284        return _sig_on_interrupt_received();
     285
     286    return 1;
     287}
     288
     289/* Macros behaving exactly like sig_on, sig_str and sig_check
     290 * but which are *not* declared cdef except 0.  This is useful if some
     291 * Cython code wants to do its own exception handling. */
     292#define sig_on_no_except()           sig_on()
     293#define sig_str_no_except(message)   sig_str(message)
     294#define sig_check_no_except()        sig_check()
     295
     296
     297/*
     298 * Temporarily block interrupts from happening inside sig_on().  This
     299 * is meant to wrap malloc() for example.  sig_unblock() checks whether
     300 * an interrupt happened in the mean time.  If yes, the interrupt is
     301 * re-raised.
     302 *
     303 * NOTES:
     304 * - This only works inside sig_on()/sig_off().  Outside of sig_on(),
     305 *   interrupts behave as usual.  This is because we can't propagate
     306 *   Python exceptions from low-level C code.
     307 * - Other signals still go through, because we can't really ignore
     308 *   SIGSEGV for example.
     309 * - For efficiency reasons, currently these may NOT be nested.
     310 *   Nesting could be implemented like src/headers/pariinl.h in PARI.
     311 */
     312static inline void sig_block()
     313{
     314    _signals.block_sigint = 1;
     315}
     316
     317static inline void sig_unblock()
     318{
     319    _signals.block_sigint = 0;
     320
     321    if (unlikely(_signals.interrupt_received) && _signals.sig_on_count > 0)
     322        kill(getpid(), SIGINT);  /* Re-raise the interrupt */
     323}
     324
     325
     326/*
     327 * Call this before raising an exception to set _signals.s. The string
     328 * s will be used as the text for the exception.  Note that s is not
     329 * copied, we just store the pointer.
    210330 */
    211331void set_sage_signal_handler_message(const char* s);
    212332
    213 /*
    214   Above error message will get truncated at this length:
    215  */
    216 #define SAGE_SIGNAL_HANDLER_MESSAGE_LEN 256
    217 
    218 
    219 /**
    220  *
    221  *
    222  */
    223 
    224 #define sig_off() _signals.mpio = 0;
    225 
    226 
    227 /* /\** */
    228 /*  * */
    229 /*  * */
    230 /*  *\/ */
    231 
    232 /* #define _sig_off_short (_signals.mpio & 4) */
    233 
    234 
    235 /**
    236  *
    237  *
    238  */
    239 
    240 /* These provide backwards compatibility with sage-4.6 and earlier */
    241 #define _sig_on        sig_on()
    242 #define _sig_str(s)    sig_str(s)
    243 #define _sig_off       sig_off()
    244 
    245 #endif /* C_LIB_INCLUDE_INTERRUPT_H */
    246333
    247334/*
    248 I thought maybe the following would work nicely, instead of just
    249 returning, but no (it crashes sometimes!).  Also the line number is
    250 not set correctly.  The only way I can imagine setting this correctly
    251 is if the following bit of code is generated within pyrex, since pyrex
    252 knows the line numbers.
     335 * Retry a failed computation starting from sig_on().  This is useful
     336 * for PARI: if PARI complains that it doesn't have enough memory, we
     337 * allocate a larger stack and retry the computation.
     338 */
     339static inline void sig_retry()
     340{
     341    /* If we're outside of sig_on(), we can't jump, so we can only bail
     342     * out */
     343    if (unlikely(_signals.sig_on_count <= 0))
     344    {
     345        fprintf(stderr, "sig_retry() without sig_on()\n");
     346        abort();
     347    }
     348    siglongjmp(_signals.env, -1);
     349}
    253350
    254                      PyErr_SetString(PyExc_RuntimeError, "(complete C-level traceback not available)"); \
    255                      __pyx_filename = __pyx_f[1]; __pyx_lineno = 0; goto __pyx_L1; \
    256                 }
    257351
    258 */
     352/*
     353 * This function does nothing, but it is declared cdef except *, so it
     354 * can be used to make Cython check whether there is a pending exception
     355 * (PyErr_Occurred() is non-NULL).
     356 * To Cython, it will look like cython_check_exception() actually
     357 * raised the exception.
     358 */
     359static inline void cython_check_exception() {return;}
     360
     361
     362#ifdef __cplusplus
     363}  /* extern "C" */
     364#endif
     365#endif /* C_LIB_INCLUDE_INTERRUPT_H */
  • c_lib/include/stdsage.h

    diff -r 2022ce865df2 -r 875182787c8a c_lib/include/stdsage.h
    a b  
    170170#define sage_realloc realloc
    171171
    172172/**
    173  * Initialisation of singal handlers, global variables, etc. Called
    174  * exactly once at SAGE start-up.
    175  *
    176  * @note: It is safe to call this function more than once but nothing
    177  * will happen after the first call.
     173 * Initialisation of signal handlers, global variables, etc. Called
     174 * exactly once at Sage start-up.
    178175 */
    179176void init_csage(void);
    180177
     178/**
     179 * Initialisation of a Cython module. Called exactly once for every
     180 * Cython module. On Cygwin, this calls init_csage().
     181 */
     182void init_csage_module(void);
     183
    181184
    182185
    183186/**
  • c_lib/src/interrupt.c

    diff -r 2022ce865df2 -r 875182787c8a c_lib/src/interrupt.c
    a b  
    1 /******************************************************************************
    2        Copyright (C) 2006 William Stein <wstein@gmail.com>
    3                      2006 Martin Albrecht <malb@informatik.uni-bremen.de>
     1/*
     2Interrupt and signal handling for Sage
    43
    5   Distributed under the terms of the GNU General Public License (GPL), Version 2.
     4AUTHORS:
    65
    7   The full text of the GPL is available at:
    8                   http://www.gnu.org/licenses/
     6- William Stein, Martin Albrecht (2006): initial version
    97
    10 ******************************************************************************/
     8- Jeroen Demeyer (2010-10-03): almost complete rewrite (#9678)
    119
     10*/
     11
     12/*****************************************************************************
     13 *       Copyright (C) 2006 William Stein <wstein@gmail.com>
     14 *                     2006 Martin Albrecht <malb@informatik.uni-bremen.de>
     15 *                     2010 Jeroen Demeyer <jdemeyer@cage.ugent.be>
     16 *
     17 *  Distributed under the terms of the GNU General Public License (GPL)
     18 *  as published by the Free Software Foundation; either version 2 of
     19 *  the License, or (at your option) any later version.
     20 *                  http://www.gnu.org/licenses/
     21 ****************************************************************************/
     22
     23#include <stdio.h>
     24#include <string.h>
     25#include <limits.h>
     26/* glibc has a backtrace() command since version 2.1 */
     27#ifdef __GLIBC__
     28#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
     29#define HAVE_BACKTRACE 1
     30#include <execinfo.h>
     31#endif
     32#endif
    1233#include "stdsage.h"
    1334#include "interrupt.h"
    14 #include <stdio.h>
    1535
    1636
    17 char sage_signal_handler_message[SAGE_SIGNAL_HANDLER_MESSAGE_LEN + 1] = "";
     37struct sage_signals_t _signals;
     38
     39/* The default signal mask during normal operation,
     40 * initialized by setup_sage_signal_handler(). */
     41static sigset_t default_sigmask;
     42
     43/* default_sigmask with SIGINT and SIGALRM added. */
     44static sigset_t sigmask_with_sigint;
     45
     46
     47/* Handler for SIGINT */
     48void sage_interrupt_handler(int sig)
     49{
     50#if ENABLE_DEBUG_INTERRUPT
     51    fprintf(stderr, "\n*** SIGINT *** %s sig_on\n", (_signals.sig_on_count > 0) ? "inside" : "outside");
     52    print_backtrace();
     53#endif
     54
     55    if (_signals.sig_on_count > 0)
     56    {
     57        if (_signals.block_sigint)
     58        {
     59            /* SIGINT is blocked, so simply set _signals.interrupt_received. */
     60            _signals.interrupt_received = 1;
     61            return;
     62        }
     63
     64        /* Raise KeyboardInterrupt */
     65        PyErr_SetNone(PyExc_KeyboardInterrupt);
     66
     67        /* Jump back to sig_on() (the first one if there is a stack) */
     68        siglongjmp(_signals.env, sig);
     69    }
     70    else
     71    {
     72        /* Set an internal Python flag that an interrupt has been
     73         * raised.  This will not immediately raise an exception, only
     74         * on the next call of PyErr_CheckSignals().  We cannot simply
     75         * raise an exception here because of Python's "global
     76         * interpreter lock" -- Jeroen Demeyer */
     77        PyErr_SetInterrupt();
     78        _signals.interrupt_received = 1;
     79    }
     80}
     81
     82/* Call sage_interrupt_handler() "by hand". */
     83void call_sage_interrupt_handler(int sig)
     84{
     85    /* Block SIGINT, SIGALRM */
     86    sigprocmask(SIG_BLOCK, &sigmask_with_sigint, NULL);
     87    sage_interrupt_handler(sig);
     88}
     89
     90
     91
     92/* Handler for SIGILL, SIGABRT, SIGFPE, SIGBUS, SIGSEGV */
     93void sage_signal_handler(int sig)
     94{
     95    sig_atomic_t inside = _signals.inside_signal_handler;
     96    _signals.inside_signal_handler = 1;
     97
     98    if (inside == 0 && _signals.sig_on_count > 0)
     99    {
     100        /* We are inside sig_on(), so we can handle the signal! */
     101
     102        /* Message to be printed in the Python exception */
     103        const char* msg = _signals.s;
     104
     105        if (!msg)
     106        {
     107            /* Default: a message depending on which signal we got */
     108            switch(sig)
     109            {
     110                case SIGILL:  msg = "Illegal instruction"; break;
     111                case SIGABRT: msg = "Aborted"; break;
     112                case SIGFPE:  msg = "Floating point exception"; break;
     113                case SIGBUS:  msg = "Bus error"; break;
     114                case SIGSEGV: msg = "Segmentation fault"; break;
     115                default: msg = "";
     116            }
     117        }
     118
     119        /* Raise RuntimeError */
     120        PyErr_SetString(PyExc_RuntimeError, msg);
     121
     122        /* Jump back to sig_on() (the first one if there is a stack) */
     123        siglongjmp(_signals.env, sig);
     124    }
     125    else
     126    {
     127        /* We are outside sig_on() and have no choice but to terminate Sage */
     128
     129        /* Reset all signals to their default behaviour and unblock
     130         * them in case something goes wrong as of now. */
     131        signal(SIGILL, SIG_DFL);
     132        signal(SIGABRT, SIG_DFL);
     133        signal(SIGFPE, SIG_DFL);
     134        signal(SIGBUS, SIG_DFL);
     135        signal(SIGSEGV, SIG_DFL);
     136        sigprocmask(SIG_SETMASK, &sigmask_with_sigint, NULL);
     137
     138        if (inside) sigdie(sig, "An error occured during signal handling.");
     139
     140        /* Quit Sage with an appropriate message. */
     141        switch(sig)
     142        {
     143            case SIGILL:
     144                sigdie(sig, "Unhandled SIGILL: An illegal instruction occurred in Sage.");
     145                break;  /* This will not be reached */
     146            case SIGABRT:
     147                sigdie(sig, "Unhandled SIGABRT: An abort() occurred in Sage.");
     148                break;  /* This will not be reached */
     149            case SIGFPE:
     150                sigdie(sig, "Unhandled SIGFPE: An unhandled floating point exception occurred in Sage.");
     151                break;  /* This will not be reached */
     152            case SIGBUS:
     153                sigdie(sig, "Unhandled SIGBUS: A bus error occurred in Sage.");
     154                break;  /* This will not be reached */
     155            case SIGSEGV:
     156                sigdie(sig, "Unhandled SIGSEGV: A segmentation fault occurred in Sage.");
     157                break;  /* This will not be reached */
     158        };
     159        sigdie(sig, "Unknown signal received.\n");
     160    }
     161}
     162
     163/* Check whether we received an interrupt before sig_on().
     164 * Return 0 if there was an interrupt, 1 otherwise. */
     165int _sig_on_interrupt_received()
     166{
     167    _signals.interrupt_received = 0;
     168    if (PyErr_CheckSignals())
     169    {
     170        _signals.sig_on_count = 0;
     171        return 0;
     172    }
     173    return 1;
     174}
     175
     176/* Recover after siglongjmp() */
     177void _sig_on_recover()
     178{
     179    _signals.block_sigint = 0;
     180    _signals.sig_on_count = 0;
     181    /* Reset signal mask */
     182    sigprocmask(SIG_SETMASK, &default_sigmask, NULL);
     183    _signals.inside_signal_handler = 0;
     184}
     185
     186void _sig_off_warning(const char* file, int line)
     187{
     188    char buf[320];
     189    snprintf(buf, sizeof(buf), "sig_off() without sig_on() at %s:%i", file, line);
     190    PyErr_WarnEx(PyExc_RuntimeWarning, buf, 2);
     191    print_backtrace();
     192}
    18193
    19194
    20195void set_sage_signal_handler_message(const char* s)
    21196{
    22    sage_signal_handler_message[SAGE_SIGNAL_HANDLER_MESSAGE_LEN] = 0;
    23    strncpy(sage_signal_handler_message, s, SAGE_SIGNAL_HANDLER_MESSAGE_LEN);
     197    _signals.s = s;
    24198}
    25199
    26200
    27 struct sage_signals _signals;
     201void setup_sage_signal_handler()
     202{
     203    /* Reset the _signals structure */
     204    memset(&_signals, 0, sizeof(_signals));
    28205
    29 void msg(char* s);
     206    /* Save the default signal mask */
     207    sigprocmask(SIG_BLOCK, NULL, &default_sigmask);
    30208
    31 void sage_signal_handler(int sig) {
     209    /* Save the signal mask with SIGINT and SIGALRM */
     210    sigprocmask(SIG_BLOCK, NULL, &sigmask_with_sigint);
     211    sigaddset(&sigmask_with_sigint, SIGINT);
     212    sigaddset(&sigmask_with_sigint, SIGALRM);
    32213
    33   char *s = _signals.s;
    34   _signals.s = NULL;
     214    /* Install signal handlers */
     215    struct sigaction sa;
     216    memset(&sa, 0, sizeof(sa));
     217    /* Block SIGINT and SIGALRM during the signal handlers */
     218    sigemptyset(&sa.sa_mask);
     219    sigaddset(&sa.sa_mask, SIGINT);
     220    sigaddset(&sa.sa_mask, SIGALRM);
    35221
    36   // if sage_signal_handler_message is non-empty, that overrides _signals.s
    37   if (sage_signal_handler_message[0])
    38   {
    39      s = sage_signal_handler_message;
    40   }
    41 
    42   //we override the default handler
    43   if ( _signals.mpio & 1 ) {
    44 
    45     //what to do?
    46 
    47     switch(sig) {
    48 
    49     case SIGINT:
    50       if( s ) {
    51         PyErr_SetString(PyExc_KeyboardInterrupt, s);
    52       } else {
    53         PyErr_SetString(PyExc_KeyboardInterrupt, "");
    54       }
    55       break;
    56 
    57     case SIGALRM:
    58       if( s ) {
    59         PyErr_SetString(PyExc_KeyboardInterrupt, s);
    60       } else {
    61         PyErr_SetString(PyExc_KeyboardInterrupt, "Alarm received");
    62       }
    63       break;
    64 
    65     default:
    66       if( s ) {
    67         PyErr_SetString(PyExc_RuntimeError, s);
    68       } else {
    69         PyErr_SetString(PyExc_RuntimeError, "");
    70       }
    71     }
    72 
    73     // clear out sage_signal_handler_message for the next time around
    74     sage_signal_handler_message[0] = 0;
    75 
    76 
    77     //notify 'calling' function
    78 
    79     _signals.mpio |= 4;
    80 
    81     signal(sig, sage_signal_handler);
    82     //where to go next?
    83     if ( _signals.mpio & 2 ) {
    84       siglongjmp(_signals.env, sig);
    85     } else {
    86       //this case shouldn't happen as _sig_[on|off]_short is disabled
    87       return;
    88     }
    89    
    90   } else {
    91 
    92     //we use the default handler
    93     _signals.mpio = 0;
    94 
    95     switch(sig) {
    96     case SIGSEGV:
    97       sig_handle_sigsegv(sig);
    98       break;
    99     case SIGBUS:
    100       sig_handle_sigbus(sig);
    101       break;
    102     case SIGFPE:
    103       sig_handle_sigfpe(sig);
    104       break;
    105     default:
    106       _signals.python_handler(sig);
    107       break;
    108     };
    109    
    110     signal(sig, sage_signal_handler);
    111   }
     222    sa.sa_handler = sage_interrupt_handler;
     223    if (sigaction(SIGINT, &sa, NULL)) {perror("sigaction"); exit(1);}
     224    sa.sa_handler = sage_signal_handler;
     225    /* Allow signals during signal handling, we have code to deal with
     226     * this case. */
     227    sa.sa_flags |= SA_NODEFER;
     228    if (sigaction(SIGILL, &sa, NULL)) {perror("sigaction"); exit(1);}
     229    if (sigaction(SIGABRT, &sa, NULL)) {perror("sigaction"); exit(1);}
     230    if (sigaction(SIGFPE, &sa, NULL)) {perror("sigaction"); exit(1);}
     231    if (sigaction(SIGBUS, &sa, NULL)) {perror("sigaction"); exit(1);}
     232    if (sigaction(SIGSEGV, &sa, NULL)) {perror("sigaction"); exit(1);}
    112233}
    113234
    114 void setup_signal_handler(void) {
    115   void *tmp = NULL;
    116235
    117   //we need to make sure not to store our own signal handler as the old one
    118   //because that would cause infinite recursion if an error occurs and we are
    119   //not supposed to catch it.
    120   tmp = signal(SIGINT, sage_signal_handler);
    121 
    122   if(sage_signal_handler != tmp) {
    123     _signals.python_handler = tmp;
    124   }
    125  
    126   _signals.s = NULL;
    127 
    128 /*  signal(SIGBUS, sig_handle_sigbus); */
    129   signal(SIGBUS, sage_signal_handler);
    130 
    131   signal(SIGALRM,sage_signal_handler);
    132   signal(SIGSEGV,sage_signal_handler);
    133   signal(SIGABRT,sage_signal_handler);
    134   signal(SIGFPE,sage_signal_handler);
     236void print_backtrace()
     237{
     238    void* backtracebuffer[1024];
     239    fflush(stderr);
     240#ifdef HAVE_BACKTRACE
     241    int btsize = backtrace(backtracebuffer, 1024);
     242    backtrace_symbols_fd(backtracebuffer, btsize, 2);
     243#endif
    135244}
    136245
    137246
    138 void msg(char* s) {
    139   fprintf(stderr, "\n\n------------------------------------------------------------\n");
    140   fprintf(stderr, s);
    141   fprintf(stderr, "This probably occurred because a *compiled* component\n");
    142   fprintf(stderr, "of Sage has a bug in it (typically accessing invalid memory)\n");
    143   fprintf(stderr, "and is not properly wrapped with sig_on(), sig_off().\n");
    144   fprintf(stderr, "You might want to run Sage under gdb with 'sage -gdb' to debug this.\n");
    145   fprintf(stderr, "Sage will now terminate (sorry).\n");
    146   fprintf(stderr, "------------------------------------------------------------\n\n");
     247void sigdie(int sig, const char* s)
     248{
     249    print_backtrace();
     250    fprintf(stderr, "\n"
     251        "------------------------------------------------------------------------\n"
     252        "%s\n"
     253        "This probably occurred because a *compiled* component of Sage has a bug\n"
     254        "in it and is not properly wrapped with sig_on(), sig_off(). You might\n"
     255        "want to run Sage under gdb with 'sage -gdb' to debug this.\n"
     256        "Sage will now terminate.\n"
     257        "------------------------------------------------------------------------\n",
     258        s);
     259    fflush(stderr);
     260
     261    /* Suicide with signal ``sig`` */
     262    kill(getpid(), sig);
     263
     264    /* We should be dead! */
     265    exit(128 + sig);
    147266}
    148 
    149 void sig_handle_sigsegv(int n) {
    150   msg("Unhandled SIGSEGV: A segmentation fault occurred in Sage.\n");
    151   PyErr_SetString(PyExc_KeyboardInterrupt, "");
    152   exit(1);
    153 }
    154 
    155 void sig_handle_sigbus(int n) {
    156   msg("Unhandled SIGBUS: A bus error occurred in Sage.\n");
    157   PyErr_SetString(PyExc_KeyboardInterrupt, "");
    158   exit(1);
    159 }
    160 
    161 void sig_handle_sigfpe(int n) {
    162   msg("Unhandled SIGFPE: An unhandled floating point exception occurred in Sage.\n");
    163   PyErr_SetString(PyExc_KeyboardInterrupt, "");
    164   exit(1);
    165 }
  • c_lib/src/stdsage.c

    diff -r 2022ce865df2 -r 875182787c8a c_lib/src/stdsage.c
    a b  
    66 */
    77   
    88/******************************************************************************
    9        Copyright (C) 2006 William Stein <wstein@gmail.com>
    10                      2006 David Harvey <dmharvey@math.harvard.edu>
    11                      2006 Martin Albrecht <malb@informatik.uni-bremen.de>
    12 
    13   Distributed under the terms of the GNU General Public License (GPL), Version 2.
    14 
    15   The full text of the GPL is available at:
    16                   http://www.gnu.org/licenses/
    17 
    18 ******************************************************************************/
     9 *     Copyright (C) 2006 William Stein <wstein@gmail.com>
     10 *                   2006 David Harvey <dmharvey@math.harvard.edu>
     11 *                   2006 Martin Albrecht <malb@informatik.uni-bremen.de>
     12 *                   2011 Jeroen Demeyer <jdemeyer@cage.ugent.be>
     13 *
     14 *  Distributed under the terms of the GNU General Public License (GPL)
     15 *  as published by the Free Software Foundation; either version 2 of
     16 *  the License, or (at your option) any later version.
     17 *                  http://www.gnu.org/licenses/
     18 ****************************************************************************/
    1919
    2020
    2121#include "stdsage.h"
     
    3838 */
    3939void global_NTL_error_callback(const char* s, void* context)
    4040{
    41    set_sage_signal_handler_message(s);
    42    abort();
     41    set_sage_signal_handler_message(s);
     42    abort();
    4343}
    4444
    4545
    46 void init_csage(void) {
    47   //_CALLED_ONLY_ONCE;
    48  
    49   init_global_empty_tuple();
    50   setup_signal_handler();
    51   setup_NTL_error_callback(global_NTL_error_callback, NULL);
     46/* This is called once during Sage startup. On some platforms like
     47 * Cygwin, this is also called from init_csage_module(). */
     48void init_csage() {
     49    init_global_empty_tuple();
     50    setup_sage_signal_handler();
     51    setup_NTL_error_callback(global_NTL_error_callback, NULL);
    5252}
     53
     54/* This is called once for every single module that links in stdsage */
     55void init_csage_module() {
     56#if defined(__CYGWIN32__)
     57    init_csage();
     58#endif
     59}
  • module_list.py

    diff -r 2022ce865df2 -r 875182787c8a module_list.py
    a b  
    234234    ##
    235235    ################################
    236236
     237    Extension('sage.ext.c_lib',
     238              sources = ['sage/ext/c_lib.pyx']),
     239   
    237240    Extension('sage.ext.fast_callable',
    238241              sources = ['sage/ext/fast_callable.pyx']),
    239242   
     
    247250              sources = ['sage/ext/multi_modular.pyx'],
    248251              libraries=['gmp']),
    249252
    250     Extension('sage.ext.sig',
    251               sources = ['sage/ext/sig.pyx']),
    252 
    253253    ################################
    254254    ##
    255255    ## sage.finance
  • sage/all.py

    diff -r 2022ce865df2 -r 875182787c8a sage/all.py
    a b  
    5656from sage.rings.memory import pmem_malloc
    5757pmem_malloc()
    5858
    59 import sage.ext.sig
    60 sage.ext.sig.get_bad_sigs()
    61 from sage.interfaces.get_sigs import get_sigs
    62 get_sigs()
     59from sage.ext.c_lib import _init_csage, sig_on_count
     60_init_csage()
    6361
    6462from sage.misc.all       import *         # takes a while
    6563
     
    6765
    6866from sage.libs.all       import *
    6967
    70 get_sigs()
    71 
    7268from sage.rings.all      import *
    7369from sage.matrix.all     import *
    7470
  • new file sage/ext/c_lib.pyx

    diff -r 2022ce865df2 -r 875182787c8a sage/ext/c_lib.pyx
    - +  
     1r"""
     2Interface between Python and c_lib.
     3
     4This allows Python code to access a few parts of c_lib.  This is not
     5needed for Cython code, since such code can access c_lib directly.
     6
     7
     8AUTHORS:
     9
     10- Jeroen Demeyer (2010-10-13): initial version
     11
     12"""
     13#*****************************************************************************
     14#       Copyright (C) 2011 Jeroen Demeyer <jdemeyer@cage.ugent.be>
     15#
     16#  Distributed under the terms of the GNU General Public License (GPL)
     17#  as published by the Free Software Foundation; either version 2 of
     18#  the License, or (at your option) any later version.
     19#                  http://www.gnu.org/licenses/
     20#*****************************************************************************
     21
     22include '../ext/stdsage.pxi'
     23include '../ext/interrupt.pxi'
     24
     25def _init_csage():
     26    """
     27    Call init_csage().
     28
     29    This is normally done exactly once during Sage startup from
     30    sage/all.py
     31    """
     32    init_csage()
     33
     34
     35def sig_on_count():
     36    """
     37    Return _signals.sig_on_count.
     38
     39    This is normally zero, but increased by every sig_on() or sig_str()
     40    and decreased by every sig_off(). In pure Python code, this should
     41    always be zero.
     42
     43    EXAMPLES::
     44
     45        sage: sig_on_count()
     46        0
     47    """
     48    return _signals.sig_on_count
  • sage/ext/cdefs.pxi

    diff -r 2022ce865df2 -r 875182787c8a sage/ext/cdefs.pxi
    a b  
    1818    int fprintf(FILE *stream, char *format, ...)
    1919    int sprintf(char *str, char *format, ...)
    2020    FILE *fopen(char *path, char *mode)
    21     int fclose(FILE *strea)
     21    int fclose(FILE *stream)
     22    int fflush(FILE *stream)
    2223    cdef FILE *stdout
    2324    int scanf(char *format, ...)
    2425
  • sage/ext/interrupt.pxi

    diff -r 2022ce865df2 -r 875182787c8a sage/ext/interrupt.pxi
    a b  
    1 ################################################################
    2 # WARNING: Only modify the version of this file in the
    3 # sage/ext/ directory.  It overwrites all other copies
    4 # of this file during the SAGE build.
    5 ################################################################
     1#
     2# See c_lib/include/interrupt.h
     3#
     4cdef extern from 'interrupt.h':
     5    int sig_on() except 0
     6    int sig_str(char*) except 0
     7    int sig_check() except 0
     8    int sig_on_no_except()
     9    int sig_str_no_except(char*)
     10    int sig_check_no_except()
     11    void sig_off()
     12    void sig_retry()
     13    void sig_block()
     14    void sig_unblock()
    615
    7 cdef extern from 'interrupt.h':
    8     void sig_on()
    9     void sig_str(char*)
    10     void sig_off()
     16    ctypedef struct sage_signals_t:
     17        int sig_on_count
     18        int sigint_received
     19        int inside_signal_handler
     20        char* s
    1121
     22    sage_signals_t _signals
     23   
    1224    # These provide backwards compatibility with sage-4.6 and earlier
    1325    int _sig_on
    1426    void _sig_str(char*)
    1527    int _sig_off
     28
     29    void cython_check_exception() except *
  • deleted file sage/ext/sig.pyx

    diff -r 2022ce865df2 -r 875182787c8a sage/ext/sig.pyx
    + -  
    1 include 'python_exc.pxi'
    2 include 'stdsage.pxi'
    3 
    4 ## cdef extern from "Python.h":
    5 ##     PyObject* PyExc_KeyboardInterrupt
    6 
    7 ## cdef extern from "signal.h":
    8 ##     int SIGSEGV
    9 ##     int SIGBUS
    10 ##     int SIGFPE
    11 ##     ctypedef void (*sighandler_t)(int)
    12 ##     void signal(int, sighandler_t)
    13    
    14 ## cdef extern from "stdio.h":
    15 ##     struct FILE
    16 ##     int fprintf(FILE *stream, char *format, ...)
    17 ##     FILE* stderr
    18 
    19 ## cdef extern from "stdlib.h":
    20 ##     void exit(int)
    21 
    22 ## cdef void msg(char* s):
    23 ##     fprintf(stderr, '\n\n------------------------------------------------------------\n')
    24 ##     fprintf(stderr, s)
    25 ##     fprintf(stderr, "This probably occurred because a *compiled* component\n")
    26 ##     fprintf(stderr, "of Sage has a bug in it (typically accessing invalid memory)\n")
    27 ##     fprintf(stderr, "or is not properly wrapped with sig_on(), sig_off().\n")
    28 ##     fprintf(stderr, "You might want to run Sage under gdb with 'sage -gdb' to debug this.\n")
    29 ##     fprintf(stderr, "Sage will now terminate (sorry).\n")
    30 ##     fprintf(stderr, '------------------------------------------------------------\n\n')
    31 
    32 ## cdef void sig_handle_sigsegv(int n):
    33 ##     msg("Unhandled SIGSEGV: A segmentation fault occurred in Sage.\n")
    34 ##     PyErr_SetString(<object>PyExc_KeyboardInterrupt, "")   
    35 ##     exit(1)
    36 
    37 ## cdef void sig_handle_sigbus(int n):
    38 ##     msg("Unhandled SIGBUS: A bus error occurred in Sage.\n")
    39 ##     PyErr_SetString(<object>PyExc_KeyboardInterrupt, "")
    40 ##     exit(1)
    41 
    42 ## cdef void sig_handle_sigfpe(int n):
    43 ##     msg("Unhandled SIGFPE: An unhandled floating point exception occurred in Sage.\n")
    44 ##     PyErr_SetString(<object>PyExc_KeyboardInterrupt, "")   
    45 ##     exit(1)
    46 
    47 def get_bad_sigs():
    48 #    signal(SIGSEGV, sig_handle_sigsegv)
    49 #    signal(SIGBUS, sig_handle_sigbus)
    50 #    signal(SIGFPE, sig_handle_sigfpe)
    51     init_csage()
    52    
  • sage/ext/stdsage.pxi

    diff -r 2022ce865df2 -r 875182787c8a sage/ext/stdsage.pxi
    a b  
    4444    void* sage_realloc(void *p, size_t n)
    4545    void* sage_malloc(size_t)
    4646    void  init_csage()
     47    void  init_csage_module()
    4748
    4849
    4950# Do this for every single module that links in stdsage.
    50 # This is necessary on some platforms, e.g., Cygwin, so
    51 # do not delete it!
    52 init_csage()
    53 
    54 
     51init_csage_module()
  • sage/interfaces/all.py

    diff -r 2022ce865df2 -r 875182787c8a sage/interfaces/all.py
    a b  
    3636from r import r, r_console, R, r_version, is_RElement
    3737from read_data import read_data
    3838
    39 # signal handling
    40 from get_sigs import *
    41 
    4239interfaces = ['gap', 'gap3', 'gp', 'mathematica', 'gnuplot', \
    4340              'kash', 'magma', 'macaulay2', 'maple', 'maxima', \
    4441              'mathematica', 'mwrank', 'octave', 'r', \
  • deleted file sage/interfaces/get_sigs.py

    diff -r 2022ce865df2 -r 875182787c8a sage/interfaces/get_sigs.py
    + -  
    1 """
    2 Grab signal handlers back from PARI or other C libraries
    3 
    4 """
    5 
    6 import signal
    7 
    8 def my_sigint(x, n):
    9     raise KeyboardInterrupt
    10 
    11 def my_sigfpe(x, n):
    12     raise RuntimeError, "A floating point exception occurred."
    13 
    14 def get_sigs():
    15     signal.signal(signal.SIGINT, my_sigint)
    16     signal.signal(signal.SIGABRT, my_sigint)
    17     signal.signal(signal.SIGFPE, my_sigfpe)
    18     signal.signal(signal.SIGALRM, my_sigint)
    19 
    20 
  • sage/libs/mwrank/interface.py

    diff -r 2022ce865df2 -r 875182787c8a sage/libs/mwrank/interface.py
    a b  
    352352
    353353            sage: EllipticCurve([0, prod(prime_range(10))]).mwrank_curve().two_descent()
    354354            sage: EllipticCurve([0, prod(prime_range(100))]).mwrank_curve().two_descent()
    355             ...
    356355            Traceback (most recent call last):
    357356            ...
    358             RuntimeError 
     357            RuntimeError: Aborted
    359358
    360359
    361360        """
  • sage/libs/pari/pari_err.pxi

    diff -r 2022ce865df2 -r 875182787c8a sage/libs/pari/pari_err.pxi
    a b  
    33cdef extern from 'pari_err.h':
    44    int _pari_catch
    55    int _pari_endcatch
    6     void sig_on "_pari_sig_on" ()
     6    int sig_on "_pari_sig_on" () except 0
     7    int sig_str "_pari_sig_str" (char *) except 0
    78    void sig_off "_pari_sig_off" ()
    8     void sig_str "_pari_sig_str" (char *)