1 # This file is part of NIT (http://www.nitlanguage.org).
3 # Copyright 2011 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Module to manage standard C signals
22 #define _POSIX_SOURCE 1
27 Structure to manage each possible signals
28 are used in an array of 32 maximum signals.
29 This array is global to the software.
31 struct nit_signals_ent {
32 char raised; /* !=0 if has been raised */
33 SignalHandler handler; /* instance to receive call */
34 char safely; /* if !=0 then manage signal safely, otherwise react when raised */
35 } nit_signals_list[32] = {0x0};
37 /* Receiver to all signals
38 If unsafe, it calls directly the Nit receiver,
39 otherwise it marks the signal as raised and returns.
41 void receiver(int sig)
43 if (sig < 32 && sig >=0)
45 if (nit_signals_list[sig].safely) {
46 nit_signals_list[sig].raised += 1;
48 SignalHandler_receive_signal(nit_signals_list[sig].handler, sig);
54 # Receives the callback from system when a given signal arise
55 interface SignalHandler
56 # Invoked after a call to `check_signals` if a signal has been raised
57 # (should be redefed by subclasses)
59 # Should be used by most signals except `sigkill` and `sigstop` since they
60 # cannot be caught, blocked or ignored.
65 # redef fun receive_signal(signal) do print "received safely {signal}"
68 # var r = new MyReceiver
69 # r.handle_signal(sigint, true) # will call back when "check_signals" is called
71 # check_signals # if a signal was received, it will invoke `r.receive_signal`
72 fun receive_signal
(signal
: Int) `{
75 # Called immediatly on receiving an unsafe signal (should be redefed by subclasses)
77 # Should be used for `sigkill` and `sigstop` since they cannot be caught,
80 # You should consider this methods as being fragile. It should be implemented in C
81 # and you should not do too much callbacks to Nit.
86 # redef fun receive_signal_unsafe(signal) do print "received unsafely {signal}"
89 # var r = new MyReceiver
90 # r.handle_signal(sigsegv, false) # `r.receive_signal_unsafe` will be invoked on sigsegv
91 fun receive_signal_unsafe
(signal
: Int) `{
94 # Set the receiver as the handler of the signal
96 # If `safely`, receiver will be called when `check_signals` in invoked
97 # otherwise the receiver is invoked when the signal is raised, it may
98 # crash the Nit system but is unavoidable for unstoppable signals.
99 fun handle_signal
(signal
: Int, safely
: Bool) import
101 SignalHandler last_handler;
102 if (signal < 32 && signal >=0) {
103 struct sigaction act;
104 sigemptyset(&act.sa_mask);
106 act.sa_handler = receiver;
108 sigaction(signal, &act, NULL);
110 last_handler = nit_signals_list[signal].handler;
111 if (last_handler != NULL)
112 SignalHandler_decr_ref(last_handler);
114 nit_signals_list[signal].handler = recv;
115 SignalHandler_incr_ref(recv);
117 nit_signals_list[signal].safely = safely;
121 # Set to ignore the signal
122 fun ignore_signal
(signal
: Int) `{
123 SignalHandler last_handler;
124 if (signal < 32 && signal >=0) {
125 struct sigaction act;
126 sigemptyset(&act.sa_mask);
128 act.sa_handler = SIG_IGN;
129 sigaction(signal, &act, NULL);
131 last_handler = nit_signals_list[signal].handler;
132 if (last_handler != NULL)
133 SignalHandler_decr_ref(last_handler);
137 # Set default action for the signal
138 fun default_signal
(signal
: Int) `{
139 SignalHandler last_handler;
140 if (signal < 32 && signal >=0) {
141 struct sigaction act;
142 sigemptyset(&act.sa_mask);
144 act.sa_handler = SIG_DFL;
145 sigaction(signal, &act, NULL);
147 last_handler = nit_signals_list[signal].handler;
148 if (last_handler != NULL)
149 SignalHandler_decr_ref(last_handler);
154 redef interface Object
156 # Check signals for safe operation
157 # will callback receiver of raised signals
158 # can callback any instance of SignalHandler, not just this one
159 protected fun check_signals
: Bool is extern import SignalHandler.receive_signal
`{
161 int raised_something = 0;
163 for (sig = 0; sig < 32; sig ++)
164 if (nit_signals_list[sig].raised) {
165 nit_signals_list[sig].raised = 0;
166 raised_something = 1;
167 SignalHandler_receive_signal(nit_signals_list[sig].handler, sig);
170 return raised_something;
174 # can callback any instance of SignalHandler, not just this one
175 protected fun set_alarm
(sec
: Int) `{ alarm(sec); `}
179 # Send a signal to the process
180 fun signal(signal: Int) do native_kill(id, signal)
182 # Send the kill signal to the process
183 fun kill do signal(sigkill)
185 # Native implementation of `signal
`
186 private fun native_kill(pid, signal: Int) `{ kill(pid, signal); `}
189 # Hang up detected on controlling terminal or death of controlling process
190 protected fun sighup
: Int do return 1
192 # Issued if the user sends an interrupt signal
193 protected fun sigint
: Int do return 2
195 # Issued if the user sends a quit signal
196 protected fun sigquit
: Int do return 3
198 # Issued if the user attempts to execute an illegal, malformed, unknown, or privileged instruction
199 protected fun sigill
: Int do return 4
201 # Issued when an exception occurs: a condition that a debugger has requested to be informed of
202 protected fun sigtrap
: Int do return 5
204 # This signal is sent to a process to tell it to abort, i. e. to terminate
205 protected fun sigabrt
: Int do return 6
207 # This signal is sent to a process when it causes a bus error
208 protected fun sigbus
: Int do return 7
210 # Issued if an illegal mathematical operation is attempted
211 protected fun sigfpe
: Int do return 8
213 # If a process gets this signal it must quit immediately and will not perform any clean-up operations
214 protected fun sigkill
: Int do return 9
216 # Sent to a process to indicate user-defined conditions
217 protected fun sigusr1
: Int do return 10
219 # Sent to a process when it makes an invalid virtual memory reference, or segmentation fault
220 protected fun sigsegv
: Int do return 11
222 # Sent to a process to indicate user-defined conditions
223 protected fun sigusr2
: Int do return 12
225 # Sent to a process when it attempts to write to a pipe without a process connected to the other end
226 protected fun sigpipe
: Int do return 13
229 protected fun sigalarm
: Int do return 14
231 # Software termination signal
232 protected fun sigterm
: Int do return 15
234 # Sent to a process when a child process terminates or is interrupted
235 protected fun sigchild
: Int do return 17
237 # Tell the operating system to continue (restart) a process previously paused by the SIGSTOP or SIGTSTP signal
238 protected fun sigcont
: Int do return 18
240 # Tell the operating system to stop a process
241 protected fun sigstop
: Int do return 19
243 # Sent to a process by its terminal to request it to stop temporarily
244 protected fun sigtstp
: Int do return 20
246 # Sent to a process when a socket has urgent or out-of-band data available to read
247 protected fun sigurg
: Int do return 23
249 # Sent to a process when it has used the CPU for a duration that exceeds a user-settable value
250 protected fun sigxcpu
: Int do return 24
252 # Sent to a process when it grows a file larger than the maximum allowed size
253 protected fun sigxfsz
: Int do return 25
255 # Virtual timer expired
256 protected fun sigvtalrm
: Int do return 26
258 # Profiling timer expired
259 protected fun sigprof
: Int do return 27
261 # Sent to a process when its controlling terminal changes its window size
262 protected fun sigwinch
: Int do return 28
264 # Sent to a process when the system experiences a power failure
265 protected fun sigpwr
: Int do return 30
267 # Sent to a process when it passes a bad argument to a system call
268 protected fun sigsys
: Int do return 31