numpy
2.0.0
|
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 */