Ticket #10030: 10030_interrupt_test.patch

File 10030_interrupt_test.patch, 27.1 KB (added by jdemeyer, 8 years ago)

SAGELIB patch

  • module_list.py

    # HG changeset patch
    # User Jeroen Demeyer <jdemeyer@cage.ugent.be>
    # Date 1286086906 -7200
    # Node ID e7d46e6ecc54690589a58063b1ac92ebb72eae5c
    # Parent  084aebab4fc21c4404a4590894159ecb615c6dda
    #10030: Testing module for interrupt/signal handling
    
    diff -r 084aebab4fc2 -r e7d46e6ecc54 module_list.py
    a b  
    16441644              depends = ginac_depends + numpy_depends,
    16451645              libraries = ["pynac", "gmp"]),
    16461646
     1647    ################################
     1648    ##
     1649    ## sage.tests
     1650    ##
     1651    ################################
     1652    Extension('sage.tests.interrupt',
     1653              sources = ['sage/tests/interrupt.pyx', 'sage/tests/c_lib.c']),
     1654   
    16471655    ]
    16481656
    16491657# Optional extensions :
  • sage/schemes/elliptic_curves/descent_two_isogeny.pyx

    diff -r 084aebab4fc2 -r e7d46e6ecc54 sage/schemes/elliptic_curves/descent_two_isogeny.pyx
    a b  
    11361136   
    11371137    Here we contrive an example to demonstrate that a keyboard interrupt
    11381138    is caught. Here we let `E` be the smallest optimal curve with two-torsion
    1139     and nontrivial Sha[2]. This ensures that the two-descent will be looking
     1139    and nontrivial `Sha[2]`. This ensures that the two-descent will be looking
    11401140    for rational points which do not exist, and by setting global_limit_large
    1141     to a very high bound, it will still be working when we simulate a ctrl-c::
     1141    to a very high bound, it will still be working when we simulate a ``CTRL-C``::
    11421142   
    11431143        sage: from sage.schemes.elliptic_curves.descent_two_isogeny import two_descent_by_two_isogeny
    1144         sage: import signal
     1144        sage: import sage.tests.interrupt
    11451145        sage: E = EllipticCurve('960d'); E
    11461146        Elliptic Curve defined by y^2 = x^3 - x^2 - 900*x - 10098 over Rational Field
    11471147        sage: E.sha().an()
    11481148        4
    11491149        sage: try:
    1150         ...     signal.alarm(2)
     1150        ...     sage.tests.interrupt.interrupt_after_delay(1000)
    11511151        ...     two_descent_by_two_isogeny(E, global_limit_large=10^8)
    11521152        ... except KeyboardInterrupt:
    11531153        ...     print "Caught!"
    1154         0
    1155         ... Caught!
    1156 
     1154        Caught!
    11571155    """
    11581156    cdef Integer a1, a2, a3, a4, a6, s2, s4, s6
    11591157    cdef Integer c, d, x0
  • new file sage/tests/c_lib.c

    diff -r 084aebab4fc2 -r e7d46e6ecc54 sage/tests/c_lib.c
    - +  
     1/*
     2 * C functions for use in sage/tests
     3 */
     4
     5#include <stdlib.h>
     6#include <stdio.h>
     7#include <string.h>
     8#include <sys/types.h>
     9#include <time.h>
     10#include <unistd.h>
     11#include <signal.h>
     12#include <sys/select.h>
     13#include <sys/wait.h>
     14
     15void ms_sleep(long ms)
     16{
     17    struct timespec t;
     18    t.tv_sec = (ms / 1000);
     19    t.tv_nsec = (ms % 1000) * 1000000;
     20    pselect(0, NULL, NULL, NULL, &t, NULL);
     21}
     22
     23
     24/* Signal process ``killpid`` with signal ``signum`` after ``ms``
     25 * milliseconds.  Wait ``interval`` milliseconds, then signal again.
     26 * Repeat this until ``n`` signals have been sent.
     27 *
     28 * This works as follows:
     29 *  - create a first child process in a new process group
     30 *  - the main process waits until the first child process terminates
     31 *  - this child process creates a second child process
     32 *  - the second child process kills the first child process
     33 *  - the main process sees that the first child process is killed
     34 *    and continues with Sage
     35 *  - the second child process does the actual waiting and signalling
     36 */
     37void signal_pid_after_delay(int signum, pid_t killpid, long ms, long interval, int n)
     38{
     39    pid_t child1 = fork();
     40    if (child1 == -1) {perror("fork"); exit(1);}
     41
     42    if (!child1)
     43    {
     44        /* This is child process 1 */
     45        child1 = getpid();
     46
     47        /* New process group to prevent us getting the signals. */
     48        setpgid(0,0);
     49
     50        /* Make sure SIGTERM simply terminates the process */
     51        signal(SIGTERM, SIG_DFL);
     52
     53        pid_t child2 = fork();
     54        if (child2 == -1) exit(1);
     55
     56        if (!child2)
     57        {
     58            /* This is child process 2 */
     59            kill(child1, SIGTERM);
     60
     61            /* Signal Sage after delay */
     62            ms_sleep(ms);
     63            for (;;)
     64            {
     65                kill(killpid, signum);
     66                if (--n == 0) exit(0);
     67                ms_sleep(interval);
     68            }
     69        }
     70
     71        /* Wait to be killed by child process 2... */
     72        /* We use a 2-second timeout in case there is trouble. */
     73        ms_sleep(2000);
     74        exit(2);  /* This should NOT be reached */
     75    }
     76
     77    /* Main Sage process, continue when child 1 finishes */
     78    int wait_status;
     79    waitpid(child1, &wait_status, 0);
     80}
  • new file sage/tests/c_lib.h

    diff -r 084aebab4fc2 -r e7d46e6ecc54 sage/tests/c_lib.h
    - +  
     1/*
     2 * C functions for use in sage/tests
     3 */
     4
     5#ifndef SAGE_TESTS_C_LIB_H
     6#define SAGE_TESTS_C_LIB_H
     7
     8#include <sys/types.h>
     9
     10/* Wait ``ms`` milliseconds */
     11void ms_sleep(long ms);
     12
     13/*
     14 * Wait ``ms`` milliseconds, then signal ``killpid`` with signal
     15 * ``signum``.  Wait ``interval`` milliseconds, then signal again.
     16 * Repeat this until ``n`` signals have been sent.  Usually, ``n``
     17 * will be equal to 1.  In that case, ``interval`` is irrelevant.
     18 */
     19void signal_pid_after_delay(int signum, pid_t killpid, long ms, long interval, int n);
     20
     21/* Signal the Sage process */
     22#define signal_after_delay(signum, ms) signal_pid_after_delay(signum, getpid(), ms, 0, 1)
     23
     24/* The same as above, but sending ``n`` signals */
     25#define signals_after_delay(signum, ms, interval, n) signal_pid_after_delay(signum, getpid(), ms, interval, n)
     26
     27
     28#endif
  • new file sage/tests/interrupt.pyx

    diff -r 084aebab4fc2 -r e7d46e6ecc54 sage/tests/interrupt.pyx
    - +  
     1"""
     2Test signal handling in Sage.
     3
     4AUTHORS:
     5
     6 - Jeroen Demeyer (2010-09-29): initial version
     7
     8"""
     9#*****************************************************************************
     10#       Copyright (C) 2010 Jeroen Demeyer <jdemeyer@cage.ugent.be>
     11#
     12#  Distributed under the terms of the GNU General Public License (GPL)
     13#  as published by the Free Software Foundation; either version 2 of
     14#  the License, or (at your option) any later version.
     15#                  http://www.gnu.org/licenses/
     16#*****************************************************************************
     17
     18
     19import signal
     20
     21cdef extern from 'stdlib.h':
     22    void abort()
     23
     24cdef extern from 'signal.h':
     25    int SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGKILL, \
     26        SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, SIGBUS
     27
     28cdef extern from '../tests/c_lib.h':
     29    void ms_sleep(long ms)
     30    void signal_after_delay(int signum, long ms)
     31    void signals_after_delay(int signum, long ms, long interval, int n)
     32
     33cdef extern from *:
     34    ctypedef int volatile_int "volatile int"
     35
     36
     37include '../ext/interrupt.pxi'
     38include '../ext/stdsage.pxi'
     39
     40
     41# Default delay in milliseconds before raising signals
     42cdef long DEFAULT_DELAY = 200
     43
     44
     45########################################################################
     46# C helper functions                                                   #
     47########################################################################
     48cdef void infinite_loop():
     49    while True:
     50        pass
     51
     52cdef void infinite_malloc_loop():
     53    cdef size_t s = 1
     54    while True:
     55        sage_free(sage_malloc(s))
     56        s *= 2
     57        if (s > 1000000): s = 1
     58
     59cdef void segmentation_fault():
     60    cdef long* ptr = <long*>(0)
     61    ptr[0] += 1
     62
     63
     64########################################################################
     65# Python helper functions                                              #
     66########################################################################
     67def raise_KeyboardInterrupt():
     68    """
     69    Raise a KeyboardInterrupt.
     70    """
     71    raise KeyboardInterrupt, "raise test"
     72
     73def try_sigint(f):
     74    """
     75    Calls the Python function ``f`` and catch any KeyboardInterrupts.
     76    This function is needed because the doctest program stops whenever
     77    it sees a KeyboardInterrupt.
     78   
     79    EXAMPLES::
     80       
     81        sage: from sage.tests.interrupt import *
     82        sage: try_sigint(raise_KeyboardInterrupt)
     83        KeyboardInterrupt: raise test
     84    """
     85    try:
     86        f()
     87    except KeyboardInterrupt, err:
     88        print "KeyboardInterrupt:", err
     89
     90def interrupt_after_delay(ms_delay = 500):
     91    """
     92    Send an interrupt signal (``SIGINT``) to the Sage process
     93    after a delay of ``ms_delay`` milliseconds.
     94
     95    INPUT::
     96   
     97    - ``ms_delay`` - (default: 500) a nonnegative integer indicating
     98      how many milliseconds to wait before raising the interrupt signal.
     99
     100    EXAMPLES:
     101
     102    This function is meant to test interrupt functionality.  We
     103    demonstrate here how to test that the ``factor`` function can be
     104    interrupted::
     105
     106        sage: import sage.tests.interrupt
     107        sage: try:
     108        ...     sage.tests.interrupt.interrupt_after_delay()
     109        ...     factor(10^1000 + 3)
     110        ... except KeyboardInterrupt:
     111        ...     print "Caught KeyboardInterrupt"
     112        Caught KeyboardInterrupt
     113    """
     114    signal_after_delay(SIGINT, ms_delay)
     115
     116
     117########################################################################
     118# Test basic macros from c_lib/headers/interrupt.h                     #
     119########################################################################
     120def test_sig_off():
     121    """
     122    TESTS::
     123       
     124        sage: from sage.tests.interrupt import *
     125        sage: test_sig_off()
     126    """
     127    sig_on()
     128    sig_off()
     129
     130def test_sig_on(long delay = DEFAULT_DELAY):
     131    """
     132    TESTS::
     133       
     134        sage: from sage.tests.interrupt import *
     135        sage: try_sigint(test_sig_on)
     136        KeyboardInterrupt:
     137    """
     138    signal_after_delay(SIGINT, delay)
     139    sig_on()
     140    infinite_loop()
     141
     142def test_sig_str(long delay = DEFAULT_DELAY):
     143    """
     144    TESTS::
     145       
     146        sage: from sage.tests.interrupt import *
     147        sage: test_sig_str()
     148        Traceback (most recent call last):
     149        ...
     150        RuntimeError: Everything ok!
     151    """
     152    signal_after_delay(SIGABRT, delay)
     153    sig_str("Everything ok!")
     154    infinite_loop()
     155
     156cdef c_test_sig_on_cython():
     157    sig_on()
     158    infinite_loop()
     159
     160def test_sig_on_cython(long delay = DEFAULT_DELAY):
     161    """
     162    TESTS::
     163       
     164        sage: from sage.tests.interrupt import *
     165        sage: try_sigint(test_sig_on_cython)
     166        KeyboardInterrupt:
     167    """
     168    signal_after_delay(SIGINT, delay)
     169    c_test_sig_on_cython()
     170
     171cdef int c_test_sig_on_cython_except() except 42:
     172    sig_on()
     173    infinite_loop()
     174
     175def test_sig_on_cython_except(long delay = DEFAULT_DELAY):
     176    """
     177    TESTS::
     178       
     179        sage: from sage.tests.interrupt import *
     180        sage: try_sigint(test_sig_on_cython_except)
     181        KeyboardInterrupt:
     182    """
     183    signal_after_delay(SIGINT, delay)
     184    c_test_sig_on_cython_except()
     185
     186cdef void c_test_sig_on_cython_except_all() except *:
     187    sig_on()
     188    infinite_loop()
     189
     190def test_sig_on_cython_except_all(long delay = DEFAULT_DELAY):
     191    """
     192    TESTS::
     193       
     194        sage: from sage.tests.interrupt import *
     195        sage: try_sigint(test_sig_on_cython_except_all)
     196        KeyboardInterrupt:
     197    """
     198    signal_after_delay(SIGINT, delay)
     199    c_test_sig_on_cython_except_all()
     200
     201def test_sig_check(long delay = DEFAULT_DELAY):
     202    """
     203    TESTS::
     204
     205        sage: from sage.tests.interrupt import *
     206        sage: try_sigint(test_sig_check)
     207        KeyboardInterrupt:
     208    """
     209    signal_after_delay(SIGINT, delay)
     210    while True:
     211        sig_check()
     212
     213def test_sig_check_inside_sig_on(long delay = DEFAULT_DELAY):
     214    """
     215    TESTS::
     216
     217        sage: from sage.tests.interrupt import *
     218        sage: try_sigint(test_sig_check_inside_sig_on)
     219        KeyboardInterrupt:
     220    """
     221    signal_after_delay(SIGINT, delay)
     222    sig_on()
     223    while True:
     224        sig_check()
     225
     226def test_sig_retry():
     227    """
     228    TESTS::
     229
     230        sage: from sage.tests.interrupt import *
     231        sage: test_sig_retry()
     232        10
     233    """
     234    cdef volatile_int v = 0
     235
     236    sig_on()
     237    if v < 10:
     238        v = v + 1
     239        sig_retry()
     240    sig_off()
     241    return v
     242
     243def test_sig_retry_and_signal(long delay = DEFAULT_DELAY):
     244    """
     245    TESTS::
     246
     247        sage: from sage.tests.interrupt import *
     248        sage: try_sigint(test_sig_retry_and_signal)
     249        KeyboardInterrupt:
     250    """
     251    cdef volatile_int v = 0
     252
     253    sig_on()
     254    if v < 10:
     255        v = v + 1
     256        sig_retry()
     257    signal_after_delay(SIGINT, delay)
     258    infinite_loop()
     259
     260########################################################################
     261# Test no_except macros                                                #
     262########################################################################
     263def test_sig_on_no_except(long delay = DEFAULT_DELAY):
     264    """
     265    TESTS::
     266       
     267        sage: from sage.tests.interrupt import *
     268        sage: test_sig_on_no_except()
     269        42
     270    """
     271    if not sig_on_no_except():
     272        # We should never get here, because this sig_on_no_except()
     273        # will not catch a signal.
     274        print "Unexpected zero returned from sig_on_no_except()"
     275    sig_off()
     276
     277    signal_after_delay(SIGINT, delay)
     278    if not sig_on_no_except():
     279        # We get here when we caught a signal.  An exception
     280        # has been raised, but Cython doesn't realize it yet.
     281        try:
     282            # Make Cython realize that there is an exception.
     283            # To Cython, it will look like the exception was raised on
     284            # the following line, so the try/except should work.
     285            cython_check_exception()
     286        except KeyboardInterrupt:
     287            return 42
     288        return 0 # fail
     289    infinite_loop()
     290
     291def test_sig_str_no_except(long delay = DEFAULT_DELAY):
     292    """
     293    TESTS::
     294       
     295        sage: from sage.tests.interrupt import *
     296        sage: test_sig_str_no_except()
     297        Traceback (most recent call last):
     298        ...
     299        RuntimeError: Everything ok!
     300    """
     301    if not sig_on_no_except():
     302        # We should never get here, because this sig_on_no_except()
     303        # will not catch a signal.
     304        print "Unexpected zero returned from sig_on_no_except()"
     305    sig_off()
     306
     307    signal_after_delay(SIGABRT, delay)
     308    if not sig_str_no_except("Everything ok!"):
     309        cython_check_exception()
     310        return 0 # fail
     311    infinite_loop()
     312
     313
     314def test_sig_check_no_except(long delay = DEFAULT_DELAY):
     315    """
     316    TESTS::
     317
     318        sage: from sage.tests.interrupt import *
     319        sage: try_sigint(test_sig_check_no_except)
     320        KeyboardInterrupt:
     321    """
     322    signal_after_delay(SIGINT, delay)
     323    while True:
     324        if not sig_check_no_except():
     325            cython_check_exception()
     326            return 0 # fail
     327
     328
     329########################################################################
     330# Test deprecated macros for backwards compatibility                   #
     331########################################################################
     332def test_old_sig_off():
     333    """
     334    TESTS::
     335       
     336        sage: from sage.tests.interrupt import *
     337        sage: test_old_sig_off()
     338    """
     339    _sig_on
     340    _sig_off
     341
     342def test_old_sig_on(long delay = DEFAULT_DELAY):
     343    """
     344    TESTS::
     345       
     346        sage: from sage.tests.interrupt import *
     347        sage: try_sigint(test_old_sig_on)
     348        KeyboardInterrupt:
     349    """
     350    signal_after_delay(SIGINT, delay)
     351    _sig_on
     352    infinite_loop()
     353
     354def test_old_sig_str(long delay = DEFAULT_DELAY):
     355    """
     356    TESTS::
     357       
     358        sage: from sage.tests.interrupt import *
     359        sage: test_old_sig_str()
     360        Traceback (most recent call last):
     361        ...
     362        RuntimeError: Everything ok!
     363    """
     364    signal_after_delay(SIGABRT, delay)
     365    _sig_str("Everything ok!")
     366    infinite_loop()
     367
     368
     369########################################################################
     370# Test different signals                                               #
     371########################################################################
     372def test_signal_segv(long delay = DEFAULT_DELAY):
     373    """
     374    TESTS::
     375       
     376        sage: from sage.tests.interrupt import *
     377        sage: test_signal_segv()
     378        Traceback (most recent call last):
     379        ...
     380        RuntimeError: Segmentation fault
     381    """
     382    signal_after_delay(SIGSEGV, delay)
     383    sig_on()
     384    infinite_loop()
     385
     386def test_signal_fpe(long delay = DEFAULT_DELAY):
     387    """
     388    TESTS::
     389       
     390        sage: from sage.tests.interrupt import *
     391        sage: test_signal_fpe()
     392        Traceback (most recent call last):
     393        ...
     394        RuntimeError: Floating point exception
     395    """
     396    signal_after_delay(SIGFPE, delay)
     397    sig_on()
     398    infinite_loop()
     399
     400def test_signal_ill(long delay = DEFAULT_DELAY):
     401    """
     402    TESTS::
     403       
     404        sage: from sage.tests.interrupt import *
     405        sage: test_signal_ill()
     406        Traceback (most recent call last):
     407        ...
     408        RuntimeError: Illegal instruction
     409    """
     410    signal_after_delay(SIGILL, delay)
     411    sig_on()
     412    infinite_loop()
     413
     414def test_signal_abrt(long delay = DEFAULT_DELAY):
     415    """
     416    TESTS::
     417       
     418        sage: from sage.tests.interrupt import *
     419        sage: test_signal_abrt()
     420        Traceback (most recent call last):
     421        ...
     422        RuntimeError: Aborted
     423    """
     424    signal_after_delay(SIGABRT, delay)
     425    sig_on()
     426    infinite_loop()
     427
     428def test_signal_bus(long delay = DEFAULT_DELAY):
     429    """
     430    TESTS::
     431       
     432        sage: from sage.tests.interrupt import *
     433        sage: test_signal_bus()
     434        Traceback (most recent call last):
     435        ...
     436        RuntimeError: Bus error
     437    """
     438    signal_after_delay(SIGBUS, delay)
     439    sig_on()
     440    infinite_loop()
     441
     442
     443########################################################################
     444# Test with "true" errors (not signals raised by hand)                 #
     445########################################################################
     446def test_segmentation_fault():
     447    """
     448    TESTS::
     449       
     450        sage: from sage.tests.interrupt import *
     451        sage: test_segmentation_fault()
     452        Traceback (most recent call last):
     453        ...
     454        RuntimeError: Segmentation fault
     455    """
     456    sig_on()
     457    segmentation_fault()
     458
     459def unguarded_segmentation_fault():
     460    """
     461    TESTS:
     462
     463    We run Sage in a subprocess and make it experience a true segmentation fault::
     464
     465        sage: from subprocess import *
     466        sage: cmd = 'from sage.tests.interrupt import *; unguarded_segmentation_fault()'
     467        sage: print '---'; print Popen(['sage', '-c', cmd], stdout=PIPE, stderr=PIPE).communicate()[1]  # long time
     468        -...
     469        ------------------------------------------------------------------------
     470        Unhandled SIGSEGV: A segmentation fault occurred in Sage.
     471        This probably occurred because a *compiled* component of Sage has a bug
     472        in it and is not properly wrapped with sig_on(), sig_off(). You might
     473        want to run Sage under gdb with 'sage -gdb' to debug this.
     474        Sage will now terminate.
     475        ------------------------------------------------------------------------
     476        ...
     477    """
     478    segmentation_fault()
     479
     480def test_abort():
     481    """
     482    TESTS::
     483       
     484        sage: from sage.tests.interrupt import *
     485        sage: test_abort()
     486        Traceback (most recent call last):
     487        ...
     488        RuntimeError: Aborted
     489    """
     490    sig_on()
     491    abort()
     492
     493def unguarded_abort():
     494    """
     495    TESTS:
     496
     497    We run Sage in a subprocess and make it call abort()::
     498
     499        sage: from subprocess import *
     500        sage: cmd = 'from sage.tests.interrupt import *; unguarded_abort()'
     501        sage: print '---'; print Popen(['sage', '-c', cmd], stdout=PIPE, stderr=PIPE).communicate()[1]  # long time
     502        -...
     503        ------------------------------------------------------------------------
     504        Unhandled SIGABRT: An abort() occurred in Sage.
     505        This probably occurred because a *compiled* component of Sage has a bug
     506        in it and is not properly wrapped with sig_on(), sig_off(). You might
     507        want to run Sage under gdb with 'sage -gdb' to debug this.
     508        Sage will now terminate.
     509        ------------------------------------------------------------------------
     510        ...
     511    """
     512    abort()
     513
     514def test_bad_str(long delay = DEFAULT_DELAY):
     515    """
     516    TESTS:
     517
     518    We run Sage in a subprocess and induce an error during the signal handler::
     519
     520        sage: from subprocess import *
     521        sage: cmd = 'from sage.tests.interrupt import *; test_bad_str()'
     522        sage: print '---'; print Popen(['sage', '-c', cmd], stdout=PIPE, stderr=PIPE).communicate()[1]  # long time
     523        -...
     524        ------------------------------------------------------------------------
     525        An error occured during signal handling.
     526        This probably occurred because a *compiled* component of Sage has a bug
     527        in it and is not properly wrapped with sig_on(), sig_off(). You might
     528        want to run Sage under gdb with 'sage -gdb' to debug this.
     529        Sage will now terminate.
     530        ------------------------------------------------------------------------
     531        ...
     532    """
     533    signal_after_delay(SIGSEGV, delay)
     534    cdef char* s = <char*>(16)
     535    sig_str(s)
     536    infinite_loop()
     537
     538
     539########################################################################
     540# Test various usage scenarios for sig_on()/sig_off()                  #
     541########################################################################
     542def test_sig_on_cython_after_delay(long delay = DEFAULT_DELAY):
     543    """
     544    TESTS::
     545       
     546        sage: from sage.tests.interrupt import *
     547        sage: try_sigint(test_sig_on_cython_after_delay)
     548        KeyboardInterrupt:
     549    """
     550    signal_after_delay(SIGINT, delay)
     551    ms_sleep(delay * 2)  # We get signaled during this sleep
     552    sig_on()             # The signal should be detected here
     553    abort()              # This should not be reached
     554
     555def test_sig_on_inside_try(long delay = DEFAULT_DELAY):
     556    """
     557    TESTS::
     558       
     559        sage: from sage.tests.interrupt import *
     560        sage: test_sig_on_inside_try()
     561    """
     562    signal_after_delay(SIGABRT, delay)
     563    try:
     564        sig_on()
     565        infinite_loop()
     566    except RuntimeError:
     567        pass
     568
     569def test_interrupt_bomb(int n = 100, int p = 10):
     570    """
     571    Have `p` processes each sending `n` interrupts in very quick
     572    succession and see what happens :-)
     573
     574    TESTS::
     575       
     576        sage: from sage.tests.interrupt import *
     577        sage: test_interrupt_bomb()  # long time (1200 + 5*p + 10*n milliseconds)
     578        Received ... interrupts
     579    """
     580    cdef int i
     581
     582    # Spawn p processes, each sending n signals with an interval of 1 millisecond
     583    cdef long base_delay = DEFAULT_DELAY + 5*p
     584    for i in range(p):
     585        signals_after_delay(SIGINT, base_delay, 1, n)
     586
     587    # Some time later (after the smoke clears up) send a SIGABRT,
     588    # which will raise RuntimeError.
     589    signal_after_delay(SIGABRT, base_delay + 10*n + 1000)
     590    i = 0
     591    while True:
     592        try:
     593            sig_on()
     594            infinite_loop()
     595        except KeyboardInterrupt:
     596            i = i + 1
     597        except RuntimeError:
     598            break
     599    print "Received %i/%i interrupts"%(i,n*p)
     600
     601def test_sig_on_loop():
     602    """
     603    Test sig_on() and sig_off() in a loop, this is also useful for
     604    benchmarking.
     605
     606    TESTS::
     607       
     608        sage: from sage.tests.interrupt import *
     609        sage: test_sig_on_loop()
     610    """
     611    cdef int i
     612    for i in range(10000000):
     613        sig_on()
     614        sig_off()
     615
     616# Special thanks to Robert Bradshaw for suggesting the try/finally
     617# construction. -- Jeroen Demeyer
     618def test_try_finally_signal(long delay = DEFAULT_DELAY):
     619    """
     620    Test a try/finally construct for sig_on() and sig_off(), raising
     621    a signal inside the ``try``.
     622
     623    TESTS::
     624       
     625        sage: from sage.tests.interrupt import *
     626        sage: test_try_finally_signal()
     627        Traceback (most recent call last):
     628        ...
     629        RuntimeError: Aborted
     630    """
     631    sig_on()
     632    try:
     633        signal_after_delay(SIGABRT, delay)
     634        infinite_loop()
     635    finally:
     636        sig_off()
     637
     638def test_try_finally_raise():
     639    """
     640    Test a try/finally construct for sig_on() and sig_off(), raising
     641    a Python exception inside the ``try``.
     642
     643    TESTS::
     644       
     645        sage: from sage.tests.interrupt import *
     646        sage: test_try_finally_raise()
     647        Traceback (most recent call last):
     648        ...
     649        RuntimeError: Everything ok!
     650    """
     651    sig_on()
     652    try:
     653        raise RuntimeError, "Everything ok!"
     654    finally:
     655        sig_off()
     656
     657def test_try_finally_return():
     658    """
     659    Test a try/finally construct for sig_on() and sig_off(), doing a
     660    normal ``return`` inside the ``try``.
     661
     662    TESTS::
     663       
     664        sage: from sage.tests.interrupt import *
     665        sage: test_try_finally_return()
     666        'Everything ok!'
     667    """
     668    sig_on()
     669    try:
     670        return "Everything ok!"
     671    finally:
     672        sig_off()
     673
     674
     675########################################################################
     676# Test sig_block()/sig_unblock()                                       #
     677########################################################################
     678def test_sig_block(long delay = DEFAULT_DELAY):
     679    """
     680    TESTS::
     681
     682        sage: from sage.tests.interrupt import *
     683        sage: test_sig_block()
     684        42
     685    """
     686    signal_after_delay(SIGINT, delay)
     687    cdef volatile_int v = 0
     688
     689    try:
     690        sig_on()
     691    except KeyboardInterrupt:
     692        return v
     693    sig_block()
     694    ms_sleep(delay * 2)  # We get signaled during this sleep
     695    v = 42
     696    sig_unblock()        # Here, the interrupt will be handled
     697    return 1             # Never reached
     698
     699def test_sig_block_outside_sig_on(long delay = DEFAULT_DELAY):
     700    """
     701    TESTS::
     702
     703        sage: from sage.tests.interrupt import *
     704        sage: test_sig_block_outside_sig_on()
     705        'Success'
     706    """
     707    signal_after_delay(SIGINT, delay)
     708    cdef int v = 0
     709    cdef int* p = &v
     710
     711    # sig_block()/sig_unblock() shouldn't do anything
     712    # since we're outside of sig_on()
     713    sig_block()
     714    ms_sleep(delay * 2)  # We get signaled during this sleep
     715    sig_unblock()
     716
     717    try:
     718        sig_on()  # Interrupt caught here
     719    except KeyboardInterrupt:
     720        return "Success"
     721    abort()   # This should not be reached
     722
     723def test_signal_during_malloc(long delay = DEFAULT_DELAY):
     724    """
     725    Test a signal arriving during a sage_malloc() or sage_free() call.
     726    Since these are wrapped with sig_block()/sig_unblock(), we should
     727    safely be able to interrupt them.
     728
     729    TESTS::
     730
     731        sage: from sage.tests.interrupt import *
     732        sage: for i in range(4):  # Several times to reduce chances of false positive
     733        ...       test_signal_during_malloc()
     734    """
     735    signal_after_delay(SIGINT, delay)
     736    try:
     737        sig_on()
     738        infinite_malloc_loop()
     739    except KeyboardInterrupt:
     740        pass
     741