lib: update the signal module to the latest FFI spec
[nit.git] / lib / signals.nit
1 # This file is part of NIT (http://www.nitlanguage.org).
2 #
3 # Copyright 2011 Alexis Laferrière <alexis.laf@xymus.net>
4 #
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
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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.
16
17 # Module to manage standard C signals
18 module signals
19
20 `{
21 #undef _POSIX_SOURCE
22 #define _POSIX_SOURCE 1
23 #include <signal.h>
24 #include <stdio.h>
25
26 /*
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.
30 */
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};
36
37 /* Receiver to all signals
38 If unsafe, it calls directly the Nit receiver,
39 otherwise it marks the signal as raised and returns.
40 */
41 void receiver(int sig)
42 {
43 if (sig < 32 && sig >=0)
44 {
45 if (nit_signals_list[sig].safely) {
46 nit_signals_list[sig].raised += 1;
47 } else {
48 SignalHandler_receive_signal(nit_signals_list[sig].handler, sig);
49 }
50 }
51 }
52 `}
53
54 # Receives the callback from system when a given signal arise
55 interface SignalHandler
56 # Called on any signal received
57 fun receive_signal(signal: Int) `{
58 `}
59
60 # Called on any unsafe signal received
61 fun receive_signal_unsafe(signal: Int) `{
62 `}
63
64 # Set the receiver as the handler of the signal
65 # If safely, receiver will be called when check_signals in invoked
66 # otherwise the receiver is invoked when the signal is raised, it may
67 # crash the Nit system but is unavoidable for unstoppable signals
68 fun handle_signal(signal: Int, safely: Bool) import
69 receive_signal `{
70 SignalHandler last_handler;
71 if (signal < 32 && signal >=0) {
72 struct sigaction act;
73 sigemptyset(&act.sa_mask);
74 act.sa_flags = 0;
75 act.sa_handler = receiver;
76
77 sigaction(signal, &act, NULL);
78
79 last_handler = nit_signals_list[signal].handler;
80 if (last_handler != NULL)
81 SignalHandler_decr_ref(last_handler);
82
83 nit_signals_list[signal].handler = recv;
84 SignalHandler_incr_ref(recv);
85
86 nit_signals_list[signal].safely = safely;
87 }
88 `}
89
90 # Set to ignore the signal
91 fun ignore_signal(signal: Int) `{
92 SignalHandler last_handler;
93 if (signal < 32 && signal >=0) {
94 struct sigaction act;
95 sigemptyset(&act.sa_mask);
96 act.sa_flags = 0;
97 act.sa_handler = SIG_IGN;
98 sigaction(signal, &act, NULL);
99
100 last_handler = nit_signals_list[signal].handler;
101 if (last_handler != NULL)
102 SignalHandler_decr_ref(last_handler);
103 }
104 `}
105
106 # Set default action for the signal
107 fun default_signal(signal: Int) `{
108 SignalHandler last_handler;
109 if (signal < 32 && signal >=0) {
110 struct sigaction act;
111 sigemptyset(&act.sa_mask);
112 act.sa_flags = 0;
113 act.sa_handler = SIG_DFL;
114 sigaction(signal, &act, NULL);
115
116 last_handler = nit_signals_list[signal].handler;
117 if (last_handler != NULL)
118 SignalHandler_decr_ref(last_handler);
119 }
120 `}
121
122 # Hang up detected on controlling terminal or death of controlling process
123 fun sighup: Int do return 1
124
125 # Issued if the user sends an interrupt signal
126 fun sigint: Int do return 2
127
128 # Issued if the user sends a quit signal
129 fun sigquit: Int do return 3
130
131 # Issued if the user attempts to execute an illegal, malformed, unknown, or privileged instruction
132 fun sigill: Int do return 4
133
134 # Issued when an exception occurs: a condition that a debugger has requested to be informed of
135 fun sigtrap: Int do return 5
136
137 # This signal is sent to a process to tell it to abort, i. e. to terminate
138 fun sigabrt: Int do return 6
139
140 #This signal is sent to a process when it causes a bus error
141 fun sigbus: Int do return 7
142
143 # Issued if an illegal mathematical operation is attempted
144 fun sigfpe: Int do return 8
145
146 # If a process gets this signal it must quit immediately and will not perform any clean-up operations
147 fun sigkill: Int do return 9
148
149 # Sent to a process to indicate user-defined conditions
150 fun sigusr1: Int do return 10
151
152 # Sent to a process when it makes an invalid virtual memory reference, or segmentation fault
153 fun sigsegv: Int do return 11
154
155 # Sent to a process to indicate user-defined conditions
156 fun sigusr2: Int do return 12
157
158 # Sent to a process when it attempts to write to a pipe without a process connected to the other end
159 fun sigpipe: Int do return 13
160
161 # Alarm Clock signal
162 fun sigalarm: Int do return 14
163
164 # Software termination signal
165 fun sigterm: Int do return 15
166
167 # Sent to a process when a child process terminates or is interrupted
168 fun sigchild: Int do return 17
169
170 # Tell the operating system to continue (restart) a process previously paused by the SIGSTOP or SIGTSTP signal
171 fun sigcont: Int do return 18
172
173 # Tell the operating system to stop a process
174 fun sigstop: Int do return 19
175
176 # Sent to a process by its terminal to request it to stop temporarily
177 fun sigtstp: Int do return 20
178
179 # Sent to a process when a socket has urgent or out-of-band data available to read
180 fun sigurg: Int do return 23
181
182 # Sent to a process when it has used the CPU for a duration that exceeds a user-settable value
183 fun sigxcpu: Int do return 24
184
185 # Sent to a process when it grows a file larger than the maximum allowed size
186 fun sigxfsz: Int do return 25
187
188 # Virtual timer expired
189 fun sigvtalrm: Int do return 26
190
191 # Profiling timer expired
192 fun sigprof: Int do return 27
193
194 # Sent to a process when its controlling terminal changes its window size
195 fun sigwinch: Int do return 28
196
197 # Sent to a process when the system experiences a power failure
198 fun sigpwr: Int do return 30
199
200 # Sent to a process when it passes a bad argument to a system call
201 fun sigsys: Int do return 31
202
203
204 end
205
206 redef interface Object
207
208 # Check signals for safe operation
209 # will callback receiver of raised signals
210 # can callback any instance of SignalHandler, not just this one
211 protected fun check_signals: Bool is extern import SignalHandler.receive_signal `{
212 int sig;
213 int raised_something = 0;
214
215 for (sig = 0; sig < 32; sig ++)
216 if (nit_signals_list[sig].raised) {
217 nit_signals_list[sig].raised = 0;
218 raised_something = 1;
219 SignalHandler_receive_signal(nit_signals_list[sig].handler, sig);
220 }
221
222 return raised_something;
223 `}
224
225 # Set alarm signal
226 # can callback any instance of SignalHandler, not just this one
227 protected fun set_alarm(sec: Int) `{ alarm(sec); `}
228 end