blob: 309af8e0cb719ac7c666240d7b9b23ea9b0e87b2 [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
Guido van Rossumbb4ba121994-06-23 11:25:45 +000035#ifndef SIG_ERR
36#define SIG_ERR ((RETSIGTYPE (*)())-1)
37#endif
38
39/*
40 NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS
41
42 When threads are supported, we want the following semantics:
43
44 - only the main thread can set a signal handler
45 - any thread can get a signal handler
46 - signals are only delivered to the main thread
47
48 I.e. we don't support "synchronous signals" like SIGFPE (catching
49 this doesn't make much sense in Python anyway) nor do we support
50 signals as a means of inter-thread communication, since not all
51 thread implementations support that (at least our thread library
52 doesn't).
53
54 We still have the problem that in some implementations signals
55 generated by the keyboard (e.g. SIGINT) are delivered to all
56 threads (e.g. SGI), while in others (e.g. Solaris) such signals are
57 delivered to one random thread (an intermediate possibility would
58 be to deliver it to the main thread -- POSIX???). For now, we have
59 a working implementation that works in all three cases -- the
60 handler ignores signals if getpid() isn't the same as in the main
61 thread. XXX This is a hack.
62
63*/
64
65#ifdef WITH_THREAD
66#include "thread.h"
67static long main_thread;
68static pid_t main_pid;
69#endif
70
Guido van Rossum398d9fe1994-05-11 08:59:13 +000071struct signalhandler_list {
72 int tripped;
73 object *func;
74};
75
76static struct signalhandler_list sig_list[NSIG];
Guido van Rossum6299d1e1994-05-31 12:51:13 +000077static int tripped = 0; /* Speed up sigcheck() when none tripped */
Guido van Rossum398d9fe1994-05-11 08:59:13 +000078
Guido van Rossumbb4ba121994-06-23 11:25:45 +000079static object *sig_dfl_object;
80static object *sig_ign_object;
81static object *default_int_handler_object;
Guido van Rossum398d9fe1994-05-11 08:59:13 +000082
83static object *
84default_int_handler(self, arg)
85 object *self;
86 object *arg;
87{
88 err_set(KeyboardInterrupt);
89 return NULL;
90}
91
92static RETSIGTYPE
93signal_handler(sig_num)
94 int sig_num;
95{
Guido van Rossumbb4ba121994-06-23 11:25:45 +000096#ifdef WITH_THREAD
97 /* See NOTES section above */
98 if (getpid() == main_pid) {
99#endif
100 tripped++;
101 sig_list[sig_num].tripped = 1;
102#ifdef WITH_THREAD
103 }
104#endif
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000105 (void *)signal(sig_num, &signal_handler);
106}
107
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000108static object *
Guido van Rossumb6775db1994-08-01 11:34:53 +0000109signal_alarm(self, args)
110 object *self; /* Not used */
111 object *args;
112{
113 int t;
114 if (!getargs(args, "i", &t))
115 return NULL;
116 alarm(t);
117 INCREF(None);
118 return None;
119}
Guido van Rossumaa0f4c71994-08-23 13:49:37 +0000120
121static object *
122signal_pause(self, args)
123 object *self; /* Not used */
124 object *args;
125{
126 if (!getnoarg(args))
127 return NULL;
128 pause();
129 INCREF(None);
130 return None;
131}
Guido van Rossumb6775db1994-08-01 11:34:53 +0000132
133static object *
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000134signal_signal(self, args)
135 object *self; /* Not used */
136 object *args;
137{
138 object *obj;
139 int sig_num;
140 object *old_handler;
141 RETSIGTYPE (*func)();
142 if (!getargs(args, "(iO)", &sig_num, &obj))
143 return NULL;
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000144#ifdef WITH_THREAD
145 if (get_thread_ident() != main_thread) {
146 err_setstr(ValueError, "signal only works in main thread");
147 return NULL;
148 }
149#endif
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000150 if (sig_num < 1 || sig_num >= NSIG) {
151 err_setstr(ValueError, "signal number out of range");
152 return NULL;
153 }
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000154 if (obj == sig_ign_object)
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000155 func = SIG_IGN;
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000156 else if (obj == sig_dfl_object)
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000157 func = SIG_DFL;
158 else if (!is_methodobject(obj) &&
159 !is_funcobject(obj) &&
160 !is_instancemethodobject(obj)) {
161 err_setstr(TypeError,
162"signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
163 return NULL;
164 }
165 else
166 func = signal_handler;
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000167 if (signal(sig_num, func) == SIG_ERR) {
168 err_errno(RuntimeError);
169 return NULL;
170 }
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000171 old_handler = sig_list[sig_num].func;
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000172 sig_list[sig_num].tripped = 0;
173 INCREF(obj);
174 sig_list[sig_num].func = obj;
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000175 return old_handler;
176}
177
178static object *
179signal_getsignal(self, args)
180 object *self; /* Not used */
181 object *args;
182{
183 int sig_num;
184 object *old_handler;
185 if (!getargs(args, "i", &sig_num))
186 return NULL;
187 if (sig_num < 1 || sig_num >= NSIG) {
188 err_setstr(ValueError, "signal number out of range");
189 return NULL;
190 }
191 old_handler = sig_list[sig_num].func;
192 INCREF(old_handler);
193 return old_handler;
194}
195
196
197/* List of functions defined in the module */
198
199static struct methodlist signal_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000200 {"alarm", signal_alarm},
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000201 {"signal", signal_signal},
202 {"getsignal", signal_getsignal},
Guido van Rossumaa0f4c71994-08-23 13:49:37 +0000203 {"pause", signal_pause},
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000204 {NULL, NULL} /* sentinel */
205};
206
207void
208initsignal()
209{
210 object *m, *d, *x;
211 object *b_dict;
212 int i;
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000213
214#ifdef WITH_THREAD
215 main_thread = get_thread_ident();
216 main_pid = getpid();
217#endif
218
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000219 /* Create the module and add the functions */
220 m = initmodule("signal", signal_methods);
221
222 /* Add some symbolic constants to the module */
223 d = getmoduledict(m);
224
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000225 sig_dfl_object = newintobject((long)SIG_DFL);
226 dictinsert(d, "SIG_DFL", sig_dfl_object);
227 sig_ign_object = newintobject((long)SIG_IGN);
228 dictinsert(d, "SIG_IGN", sig_ign_object);
229 dictinsert(d, "NSIG", newintobject((long)NSIG));
230 default_int_handler_object = newmethodobject("default_int_handler",
231 default_int_handler,
232 (object *)NULL,
233 0);
234 dictinsert(d, "default_int_handler", default_int_handler_object);
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000235
236 sig_list[0].tripped = 0;
237 for (i = 1; i < NSIG; i++) {
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000238 RETSIGTYPE (*t)();
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000239 t = signal(i, SIG_IGN);
240 signal(i, t);
241 sig_list[i].tripped = 0;
242 if (t == SIG_DFL)
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000243 sig_list[i].func = sig_dfl_object;
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000244 else if (t == SIG_IGN)
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000245 sig_list[i].func = sig_ign_object;
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000246 else
247 sig_list[i].func = None; /* None of our business */
248 INCREF(sig_list[i].func);
249 }
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000250 if (sig_list[SIGINT].func == sig_dfl_object) {
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000251 /* Install default int handler */
252 DECREF(sig_list[SIGINT].func);
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000253 sig_list[SIGINT].func = default_int_handler_object;
254 INCREF(default_int_handler_object);
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000255 signal(SIGINT, &signal_handler);
256 }
257
258#ifdef SIGHUP
259 x = newintobject(SIGHUP);
260 dictinsert(d, "SIGHUP", x);
261#endif
262#ifdef SIGINT
263 x = newintobject(SIGINT);
264 dictinsert(d, "SIGINT", x);
265#endif
266#ifdef SIGQUIT
267 x = newintobject(SIGQUIT);
268 dictinsert(d, "SIGQUIT", x);
269#endif
270#ifdef SIGILL
271 x = newintobject(SIGILL);
272 dictinsert(d, "SIGILL", x);
273#endif
274#ifdef SIGTRAP
275 x = newintobject(SIGTRAP);
276 dictinsert(d, "SIGTRAP", x);
277#endif
278#ifdef SIGIOT
279 x = newintobject(SIGIOT);
280 dictinsert(d, "SIGIOT", x);
281#endif
282#ifdef SIGABRT
283 x = newintobject(SIGABRT);
284 dictinsert(d, "SIGABRT", x);
285#endif
286#ifdef SIGEMT
287 x = newintobject(SIGEMT);
288 dictinsert(d, "SIGEMT", x);
289#endif
290#ifdef SIGFPE
291 x = newintobject(SIGFPE);
292 dictinsert(d, "SIGFPE", x);
293#endif
294#ifdef SIGKILL
295 x = newintobject(SIGKILL);
296 dictinsert(d, "SIGKILL", x);
297#endif
298#ifdef SIGBUS
299 x = newintobject(SIGBUS);
300 dictinsert(d, "SIGBUS", x);
301#endif
302#ifdef SIGSEGV
303 x = newintobject(SIGSEGV);
304 dictinsert(d, "SIGSEGV", x);
305#endif
306#ifdef SIGSYS
307 x = newintobject(SIGSYS);
308 dictinsert(d, "SIGSYS", x);
309#endif
310#ifdef SIGPIPE
311 x = newintobject(SIGPIPE);
312 dictinsert(d, "SIGPIPE", x);
313#endif
314#ifdef SIGALRM
315 x = newintobject(SIGALRM);
316 dictinsert(d, "SIGALRM", x);
317#endif
318#ifdef SIGTERM
319 x = newintobject(SIGTERM);
320 dictinsert(d, "SIGTERM", x);
321#endif
322#ifdef SIGUSR1
323 x = newintobject(SIGUSR1);
324 dictinsert(d, "SIGUSR1", x);
325#endif
326#ifdef SIGUSR2
327 x = newintobject(SIGUSR2);
328 dictinsert(d, "SIGUSR2", x);
329#endif
330#ifdef SIGCLD
331 x = newintobject(SIGCLD);
332 dictinsert(d, "SIGCLD", x);
333#endif
334#ifdef SIGCHLD
335 x = newintobject(SIGCHLD);
336 dictinsert(d, "SIGCHLD", x);
337#endif
338#ifdef SIGPWR
339 x = newintobject(SIGPWR);
340 dictinsert(d, "SIGPWR", x);
341#endif
342#ifdef SIGIO
343 x = newintobject(SIGIO);
344 dictinsert(d, "SIGIO", x);
345#endif
346#ifdef SIGURG
347 x = newintobject(SIGURG);
348 dictinsert(d, "SIGURG", x);
349#endif
350#ifdef SIGWINCH
351 x = newintobject(SIGWINCH);
352 dictinsert(d, "SIGWINCH", x);
353#endif
354#ifdef SIGPOLL
355 x = newintobject(SIGPOLL);
356 dictinsert(d, "SIGPOLL", x);
357#endif
358#ifdef SIGSTOP
359 x = newintobject(SIGSTOP);
360 dictinsert(d, "SIGSTOP", x);
361#endif
362#ifdef SIGTSTP
363 x = newintobject(SIGTSTP);
364 dictinsert(d, "SIGTSTP", x);
365#endif
366#ifdef SIGCONT
367 x = newintobject(SIGCONT);
368 dictinsert(d, "SIGCONT", x);
369#endif
370#ifdef SIGTTIN
371 x = newintobject(SIGTTIN);
372 dictinsert(d, "SIGTTIN", x);
373#endif
374#ifdef SIGTTOU
375 x = newintobject(SIGTTOU);
376 dictinsert(d, "SIGTTOU", x);
377#endif
378#ifdef SIGVTALRM
379 x = newintobject(SIGVTALRM);
380 dictinsert(d, "SIGVTALRM", x);
381#endif
382#ifdef SIGPROF
383 x = newintobject(SIGPROF);
384 dictinsert(d, "SIGPROF", x);
385#endif
386#ifdef SIGCPU
387 x = newintobject(SIGCPU);
388 dictinsert(d, "SIGCPU", x);
389#endif
390#ifdef SIGFSZ
391 x = newintobject(SIGFSZ);
392 dictinsert(d, "SIGFSZ", x);
393#endif
394 /* Check for errors */
395 if (err_occurred())
396 fatal("can't initialize module signal");
397}
398
399int
400sigcheck()
401{
402 int i;
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000403 object *f;
404 if (!tripped)
405 return 0;
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000406#ifdef WITH_THREAD
407 if (get_thread_ident() != main_thread)
408 return 0;
409#endif
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000410 f = getframe();
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000411 if (f == NULL)
412 f = None;
413 for (i = 1; i < NSIG; i++) {
414 if (sig_list[i].tripped) {
415 object *arglist, *result;
416 sig_list[i].tripped = 0;
417 arglist = mkvalue("(iO)", i, f);
418 if (arglist == NULL)
419 result = NULL;
420 else {
421 result = call_object(sig_list[i].func,arglist);
422 DECREF(arglist);
423 }
424 if (result == NULL) {
425 return 1;
426 } else {
427 DECREF(result);
428 }
429 }
430 }
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000431 tripped = 0;
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000432 return 0;
433}
434
435/* Replacement for intrcheck.c functionality */
436
437void
438initintr()
439{
440 initsignal();
441}
442
443int
444intrcheck()
445{
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000446 if (sig_list[SIGINT].tripped) {
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000447#ifdef WITH_THREAD
448 if (get_thread_ident() != main_thread)
449 return 0;
450#endif
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000451 sig_list[SIGINT].tripped = 0;
452 return 1;
453 }
454 return 0;
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000455}