blob: c36a9cf07dc045a6f6b03e039e5a393449075f0e [file] [log] [blame]
Guido van Rossum398d9fe1994-05-11 08:59:13 +00001/***********************************************************
2Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Signal module -- many thanks to Lance Ellinghouse */
26
27#include "allobjects.h"
28#include "modsupport.h"
29#include "ceval.h"
30#include "intrcheck.h"
31
32#include <signal.h>
Guido van Rossum6299d1e1994-05-31 12:51:13 +000033#include <errno.h>
Guido van Rossum398d9fe1994-05-11 08:59:13 +000034
35struct signalhandler_list {
36 int tripped;
37 object *func;
38};
39
40static struct signalhandler_list sig_list[NSIG];
Guido van Rossum6299d1e1994-05-31 12:51:13 +000041static int tripped = 0; /* Speed up sigcheck() when none tripped */
Guido van Rossum398d9fe1994-05-11 08:59:13 +000042
43static object *default_sig_object;
44static object *default_ignore_object;
45static object *default_int_object;
46
47static object *
48default_int_handler(self, arg)
49 object *self;
50 object *arg;
51{
52 err_set(KeyboardInterrupt);
53 return NULL;
54}
55
56static RETSIGTYPE
57signal_handler(sig_num)
58 int sig_num;
59{
Guido van Rossum6299d1e1994-05-31 12:51:13 +000060 tripped++;
Guido van Rossum398d9fe1994-05-11 08:59:13 +000061 sig_list[sig_num].tripped = 1;
62 (void *)signal(sig_num, &signal_handler);
63}
64
65
66static object *
67signal_signal(self, args)
68 object *self; /* Not used */
69 object *args;
70{
71 object *obj;
72 int sig_num;
73 object *old_handler;
74 RETSIGTYPE (*func)();
75 if (!getargs(args, "(iO)", &sig_num, &obj))
76 return NULL;
77 if (sig_num < 1 || sig_num >= NSIG) {
78 err_setstr(ValueError, "signal number out of range");
79 return NULL;
80 }
81 if (obj == default_ignore_object)
82 func = SIG_IGN;
83 else if (obj == default_sig_object)
84 func = SIG_DFL;
85 else if (!is_methodobject(obj) &&
86 !is_funcobject(obj) &&
87 !is_instancemethodobject(obj)) {
88 err_setstr(TypeError,
89"signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
90 return NULL;
91 }
92 else
93 func = signal_handler;
94 old_handler = sig_list[sig_num].func;
95 /* XXX is it always correct to clear tripped? */
96 sig_list[sig_num].tripped = 0;
97 INCREF(obj);
98 sig_list[sig_num].func = obj;
99 signal(sig_num, func);
100 return old_handler;
101}
102
103static object *
104signal_getsignal(self, args)
105 object *self; /* Not used */
106 object *args;
107{
108 int sig_num;
109 object *old_handler;
110 if (!getargs(args, "i", &sig_num))
111 return NULL;
112 if (sig_num < 1 || sig_num >= NSIG) {
113 err_setstr(ValueError, "signal number out of range");
114 return NULL;
115 }
116 old_handler = sig_list[sig_num].func;
117 INCREF(old_handler);
118 return old_handler;
119}
120
121
122/* List of functions defined in the module */
123
124static struct methodlist signal_methods[] = {
125 {"signal", signal_signal},
126 {"getsignal", signal_getsignal},
127 {NULL, NULL} /* sentinel */
128};
129
130void
131initsignal()
132{
133 object *m, *d, *x;
134 object *b_dict;
135 int i;
136 /* Create the module and add the functions */
137 m = initmodule("signal", signal_methods);
138
139 /* Add some symbolic constants to the module */
140 d = getmoduledict(m);
141
142 default_sig_object = newintobject((long)SIG_DFL);
143 dictinsert(d, "SIG_IGN", default_sig_object);
144 default_ignore_object = newintobject((long)SIG_IGN);
145 dictinsert(d, "SIG_DFL", default_ignore_object);
146 default_int_object = newmethodobject("default_int_handler",
147 default_int_handler,
148 (object *)NULL,
149 0);
150 dictinsert(d, "default_int_handler", default_int_object);
151
152 sig_list[0].tripped = 0;
153 for (i = 1; i < NSIG; i++) {
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000154 RETSIGTYPE (*t)();
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000155 t = signal(i, SIG_IGN);
156 signal(i, t);
157 sig_list[i].tripped = 0;
158 if (t == SIG_DFL)
159 sig_list[i].func = default_sig_object;
160 else if (t == SIG_IGN)
161 sig_list[i].func = default_ignore_object;
162 else
163 sig_list[i].func = None; /* None of our business */
164 INCREF(sig_list[i].func);
165 }
166 if (sig_list[SIGINT].func == default_sig_object) {
167 /* Install default int handler */
168 DECREF(sig_list[SIGINT].func);
169 sig_list[SIGINT].func = default_int_object;
170 INCREF(default_int_object);
171 signal(SIGINT, &signal_handler);
172 }
173
174#ifdef SIGHUP
175 x = newintobject(SIGHUP);
176 dictinsert(d, "SIGHUP", x);
177#endif
178#ifdef SIGINT
179 x = newintobject(SIGINT);
180 dictinsert(d, "SIGINT", x);
181#endif
182#ifdef SIGQUIT
183 x = newintobject(SIGQUIT);
184 dictinsert(d, "SIGQUIT", x);
185#endif
186#ifdef SIGILL
187 x = newintobject(SIGILL);
188 dictinsert(d, "SIGILL", x);
189#endif
190#ifdef SIGTRAP
191 x = newintobject(SIGTRAP);
192 dictinsert(d, "SIGTRAP", x);
193#endif
194#ifdef SIGIOT
195 x = newintobject(SIGIOT);
196 dictinsert(d, "SIGIOT", x);
197#endif
198#ifdef SIGABRT
199 x = newintobject(SIGABRT);
200 dictinsert(d, "SIGABRT", x);
201#endif
202#ifdef SIGEMT
203 x = newintobject(SIGEMT);
204 dictinsert(d, "SIGEMT", x);
205#endif
206#ifdef SIGFPE
207 x = newintobject(SIGFPE);
208 dictinsert(d, "SIGFPE", x);
209#endif
210#ifdef SIGKILL
211 x = newintobject(SIGKILL);
212 dictinsert(d, "SIGKILL", x);
213#endif
214#ifdef SIGBUS
215 x = newintobject(SIGBUS);
216 dictinsert(d, "SIGBUS", x);
217#endif
218#ifdef SIGSEGV
219 x = newintobject(SIGSEGV);
220 dictinsert(d, "SIGSEGV", x);
221#endif
222#ifdef SIGSYS
223 x = newintobject(SIGSYS);
224 dictinsert(d, "SIGSYS", x);
225#endif
226#ifdef SIGPIPE
227 x = newintobject(SIGPIPE);
228 dictinsert(d, "SIGPIPE", x);
229#endif
230#ifdef SIGALRM
231 x = newintobject(SIGALRM);
232 dictinsert(d, "SIGALRM", x);
233#endif
234#ifdef SIGTERM
235 x = newintobject(SIGTERM);
236 dictinsert(d, "SIGTERM", x);
237#endif
238#ifdef SIGUSR1
239 x = newintobject(SIGUSR1);
240 dictinsert(d, "SIGUSR1", x);
241#endif
242#ifdef SIGUSR2
243 x = newintobject(SIGUSR2);
244 dictinsert(d, "SIGUSR2", x);
245#endif
246#ifdef SIGCLD
247 x = newintobject(SIGCLD);
248 dictinsert(d, "SIGCLD", x);
249#endif
250#ifdef SIGCHLD
251 x = newintobject(SIGCHLD);
252 dictinsert(d, "SIGCHLD", x);
253#endif
254#ifdef SIGPWR
255 x = newintobject(SIGPWR);
256 dictinsert(d, "SIGPWR", x);
257#endif
258#ifdef SIGIO
259 x = newintobject(SIGIO);
260 dictinsert(d, "SIGIO", x);
261#endif
262#ifdef SIGURG
263 x = newintobject(SIGURG);
264 dictinsert(d, "SIGURG", x);
265#endif
266#ifdef SIGWINCH
267 x = newintobject(SIGWINCH);
268 dictinsert(d, "SIGWINCH", x);
269#endif
270#ifdef SIGPOLL
271 x = newintobject(SIGPOLL);
272 dictinsert(d, "SIGPOLL", x);
273#endif
274#ifdef SIGSTOP
275 x = newintobject(SIGSTOP);
276 dictinsert(d, "SIGSTOP", x);
277#endif
278#ifdef SIGTSTP
279 x = newintobject(SIGTSTP);
280 dictinsert(d, "SIGTSTP", x);
281#endif
282#ifdef SIGCONT
283 x = newintobject(SIGCONT);
284 dictinsert(d, "SIGCONT", x);
285#endif
286#ifdef SIGTTIN
287 x = newintobject(SIGTTIN);
288 dictinsert(d, "SIGTTIN", x);
289#endif
290#ifdef SIGTTOU
291 x = newintobject(SIGTTOU);
292 dictinsert(d, "SIGTTOU", x);
293#endif
294#ifdef SIGVTALRM
295 x = newintobject(SIGVTALRM);
296 dictinsert(d, "SIGVTALRM", x);
297#endif
298#ifdef SIGPROF
299 x = newintobject(SIGPROF);
300 dictinsert(d, "SIGPROF", x);
301#endif
302#ifdef SIGCPU
303 x = newintobject(SIGCPU);
304 dictinsert(d, "SIGCPU", x);
305#endif
306#ifdef SIGFSZ
307 x = newintobject(SIGFSZ);
308 dictinsert(d, "SIGFSZ", x);
309#endif
310 /* Check for errors */
311 if (err_occurred())
312 fatal("can't initialize module signal");
313}
314
315int
316sigcheck()
317{
318 int i;
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000319 object *f;
320 if (!tripped)
321 return 0;
322 f = getframe();
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000323 if (f == NULL)
324 f = None;
325 for (i = 1; i < NSIG; i++) {
326 if (sig_list[i].tripped) {
327 object *arglist, *result;
328 sig_list[i].tripped = 0;
329 arglist = mkvalue("(iO)", i, f);
330 if (arglist == NULL)
331 result = NULL;
332 else {
333 result = call_object(sig_list[i].func,arglist);
334 DECREF(arglist);
335 }
336 if (result == NULL) {
337 return 1;
338 } else {
339 DECREF(result);
340 }
341 }
342 }
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000343 tripped = 0;
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000344 return 0;
345}
346
347/* Replacement for intrcheck.c functionality */
348
349void
350initintr()
351{
352 initsignal();
353}
354
355int
356intrcheck()
357{
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000358 if (sig_list[SIGINT].tripped) {
359 sig_list[SIGINT].tripped = 0;
360 return 1;
361 }
362 return 0;
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000363}