Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/ext/c_lib.pyx
8817 views
1
r"""
2
Interface between Python and c_lib.
3
4
This allows Python code to access a few parts of c_lib. This is not
5
needed for Cython code, since such code can access c_lib directly.
6
7
8
AUTHORS:
9
10
- Jeroen Demeyer (2010-10-13): initial version
11
12
"""
13
#*****************************************************************************
14
# Copyright (C) 2011 Jeroen Demeyer <[email protected]>
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
22
include 'sage/ext/stdsage.pxi'
23
include 'sage/ext/interrupt.pxi'
24
include 'sage/ext/cdefs.pxi'
25
include 'sage/ext/signals.pxi'
26
27
class AlarmInterrupt(KeyboardInterrupt):
28
"""
29
Exception class for :func:`alarm` timeouts.
30
31
EXAMPLES::
32
33
sage: raise AlarmInterrupt
34
Traceback (most recent call last):
35
...
36
AlarmInterrupt
37
sage: from sage.ext.c_lib import do_raise_exception
38
sage: import signal
39
sage: do_raise_exception(signal.SIGALRM)
40
Traceback (most recent call last):
41
...
42
AlarmInterrupt
43
"""
44
pass
45
46
class SignalError(BaseException):
47
"""
48
Exception class for critical signals such as ``SIGSEGV``. Inherits
49
from ``BaseException`` because these normally should not be handled.
50
51
EXAMPLES::
52
53
sage: from sage.ext.c_lib import do_raise_exception
54
sage: import signal
55
sage: do_raise_exception(signal.SIGSEGV)
56
Traceback (most recent call last):
57
...
58
SignalError: Segmentation fault
59
"""
60
pass
61
62
cdef int sig_raise_exception(int sig, const char* msg) except 0:
63
"""
64
Raise an exception for signal number ``sig`` with message ``msg``
65
(or a default message if ``msg`` is ``NULL``).
66
"""
67
if sig == SIGHUP or sig == SIGTERM:
68
# Redirect stdin from /dev/null to close interactive sessions
69
freopen("/dev/null", "r", stdin);
70
# This causes Python to exit
71
raise SystemExit
72
if sig == SIGINT:
73
raise KeyboardInterrupt
74
if sig == SIGALRM:
75
if msg == NULL:
76
msg = ""
77
raise AlarmInterrupt(msg)
78
if sig == SIGILL:
79
if msg == NULL:
80
msg = "Illegal instruction"
81
raise SignalError(msg)
82
if sig == SIGABRT:
83
if msg == NULL:
84
msg = "Aborted"
85
raise RuntimeError(msg)
86
if sig == SIGFPE:
87
if msg == NULL:
88
msg = "Floating point exception"
89
raise FloatingPointError(msg)
90
if sig == SIGBUS:
91
if msg == NULL:
92
msg = "Bus error"
93
raise SignalError(msg)
94
if sig == SIGSEGV:
95
if msg == NULL:
96
msg = "Segmentation fault";
97
raise SignalError(msg)
98
99
raise SystemError("unknown signal number %s"%sig)
100
101
def do_raise_exception(sig, msg=None):
102
"""
103
Python version of :func:`sig_raise_exception`, just for doctesting.
104
105
EXAMPLES::
106
107
sage: from sage.ext.c_lib import do_raise_exception
108
sage: import signal
109
sage: do_raise_exception(signal.SIGFPE)
110
Traceback (most recent call last):
111
...
112
FloatingPointError: Floating point exception
113
sage: do_raise_exception(signal.SIGBUS, "CUSTOM MESSAGE")
114
Traceback (most recent call last):
115
...
116
SignalError: CUSTOM MESSAGE
117
sage: do_raise_exception(0)
118
Traceback (most recent call last):
119
...
120
SystemError: unknown signal number 0
121
"""
122
cdef const char* m
123
if msg is None:
124
m = NULL
125
else:
126
m = msg
127
sig_raise_exception(sig, m)
128
129
130
def _init_csage():
131
"""
132
Call init_csage() and enable interrupts.
133
134
This is normally done exactly once during Sage startup from
135
sage/all.py
136
"""
137
# Set the Python-level interrupt handler. When a SIGINT occurs,
138
# this will not be called directly. Instead, a SIGINT is caught by
139
# the libcsage (c_lib) interrupt handler. If it happens during pure
140
# Python code (not within sig_on()/sig_off()), the handler will set
141
# Python's interrupt flag. Python regularly checks this and will
142
# call its interrupt handler (which is the one we set now). This
143
# handler issues a sig_check() which finally raises the
144
# KeyboardInterrupt exception.
145
import signal
146
signal.signal(signal.SIGINT, sage_python_check_interrupt)
147
148
init_csage()
149
_signals.raise_exception = sig_raise_exception
150
151
152
def _sig_on_reset():
153
"""
154
Return the current value of ``_signals.sig_on_count`` and set its
155
value to zero. This is used by the doctesting framework.
156
157
EXAMPLES::
158
159
sage: from sage.ext.c_lib import _sig_on_reset as sig_on_reset
160
sage: cython('sig_on()'); sig_on_reset()
161
1
162
sage: sig_on_reset()
163
0
164
"""
165
cdef int s = _signals.sig_on_count
166
_signals.sig_on_count = 0
167
return s
168
169
170
def sage_python_check_interrupt(sig, frame):
171
"""
172
Python-level interrupt handler for interrupts raised in Python
173
code. This simply delegates to the interrupt handling code in
174
libcsage (c_lib).
175
"""
176
sig_check()
177
178