numpy  2.0.0
include/numpy/npy_interrupt.h
Go to the documentation of this file.
00001 
00002 /* Signal handling:
00003 
00004 This header file defines macros that allow your code to handle
00005 interrupts received during processing.  Interrupts that
00006 could reasonably be handled:
00007 
00008 SIGINT, SIGABRT, SIGALRM, SIGSEGV
00009 
00010 ****Warning***************
00011 
00012 Do not allow code that creates temporary memory or increases reference
00013 counts of Python objects to be interrupted unless you handle it
00014 differently.
00015 
00016 **************************
00017 
00018 The mechanism for handling interrupts is conceptually simple:
00019 
00020   - replace the signal handler with our own home-grown version
00021      and store the old one.
00022   - run the code to be interrupted -- if an interrupt occurs
00023      the handler should basically just cause a return to the
00024      calling function for finish work.
00025   - restore the old signal handler
00026 
00027 Of course, every code that allows interrupts must account for
00028 returning via the interrupt and handle clean-up correctly.  But,
00029 even still, the simple paradigm is complicated by at least three
00030 factors.
00031 
00032  1) platform portability (i.e. Microsoft says not to use longjmp
00033      to return from signal handling.  They have a __try  and __except
00034      extension to C instead but what about mingw?).
00035 
00036  2) how to handle threads: apparently whether signals are delivered to
00037     every thread of the process or the "invoking" thread is platform
00038     dependent. --- we don't handle threads for now.
00039 
00040  3) do we need to worry about re-entrance.  For now, assume the
00041     code will not call-back into itself.
00042 
00043 Ideas:
00044 
00045  1) Start by implementing an approach that works on platforms that
00046     can use setjmp and longjmp functionality and does nothing
00047     on other platforms.
00048 
00049  2) Ignore threads --- i.e. do not mix interrupt handling and threads
00050 
00051  3) Add a default signal_handler function to the C-API but have the rest
00052     use macros.
00053 
00054 
00055 Simple Interface:
00056 
00057 
00058 In your C-extension: around a block of code you want to be interruptable
00059 with a SIGINT
00060 
00061 NPY_SIGINT_ON
00062 [code]
00063 NPY_SIGINT_OFF
00064 
00065 In order for this to work correctly, the
00066 [code] block must not allocate any memory or alter the reference count of any
00067 Python objects.  In other words [code] must be interruptible so that continuation
00068 after NPY_SIGINT_OFF will only be "missing some computations"
00069 
00070 Interrupt handling does not work well with threads.
00071 
00072 */
00073 
00074 /* Add signal handling macros
00075    Make the global variable and signal handler part of the C-API
00076 */
00077 
00078 #ifndef NPY_INTERRUPT_H
00079 #define NPY_INTERRUPT_H
00080 
00081 #ifndef NPY_NO_SIGNAL
00082 
00083 #include <setjmp.h>
00084 #include <signal.h>
00085 
00086 #ifndef sigsetjmp
00087 
00088 #define NPY_SIGSETJMP(arg1, arg2) setjmp(arg1)
00089 #define NPY_SIGLONGJMP(arg1, arg2) longjmp(arg1, arg2)
00090 #define NPY_SIGJMP_BUF jmp_buf
00091 
00092 #else
00093 
00094 #define NPY_SIGSETJMP(arg1, arg2) sigsetjmp(arg1, arg2)
00095 #define NPY_SIGLONGJMP(arg1, arg2) siglongjmp(arg1, arg2)
00096 #define NPY_SIGJMP_BUF sigjmp_buf
00097 
00098 #endif
00099 
00100 #    define NPY_SIGINT_ON {                                             \
00101                    PyOS_sighandler_t _npy_sig_save;                     \
00102                    _npy_sig_save = PyOS_setsig(SIGINT, _PyArray_SigintHandler); \
00103                    if (NPY_SIGSETJMP(*((NPY_SIGJMP_BUF *)_PyArray_GetSigintBuf()), \
00104                                  1) == 0) {                             \
00105 
00106 #    define NPY_SIGINT_OFF }                                      \
00107         PyOS_setsig(SIGINT, _npy_sig_save);                       \
00108         }
00109 
00110 #else /* NPY_NO_SIGNAL  */
00111 
00112 #define NPY_SIGINT_ON
00113 #define NPY_SIGINT_OFF
00114 
00115 #endif /* HAVE_SIGSETJMP */
00116 
00117 #endif /* NPY_INTERRUPT_H */