blob: 211ebe7cc35fb8788ed51b41f70ec7352ad10b26 [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
108
109static object *
110signal_signal(self, args)
111 object *self; /* Not used */
112 object *args;
113{
114 object *obj;
115 int sig_num;
116 object *old_handler;
117 RETSIGTYPE (*func)();
118 if (!getargs(args, "(iO)", &sig_num, &obj))
119 return NULL;
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000120#ifdef WITH_THREAD
121 if (get_thread_ident() != main_thread) {
122 err_setstr(ValueError, "signal only works in main thread");
123 return NULL;
124 }
125#endif
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000126 if (sig_num < 1 || sig_num >= NSIG) {
127 err_setstr(ValueError, "signal number out of range");
128 return NULL;
129 }
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000130 if (obj == sig_ign_object)
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000131 func = SIG_IGN;
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000132 else if (obj == sig_dfl_object)
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000133 func = SIG_DFL;
134 else if (!is_methodobject(obj) &&
135 !is_funcobject(obj) &&
136 !is_instancemethodobject(obj)) {
137 err_setstr(TypeError,
138"signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
139 return NULL;
140 }
141 else
142 func = signal_handler;
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000143 if (signal(sig_num, func) == SIG_ERR) {
144 err_errno(RuntimeError);
145 return NULL;
146 }
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000147 old_handler = sig_list[sig_num].func;
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000148 sig_list[sig_num].tripped = 0;
149 INCREF(obj);
150 sig_list[sig_num].func = obj;
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000151 return old_handler;
152}
153
154static object *
155signal_getsignal(self, args)
156 object *self; /* Not used */
157 object *args;
158{
159 int sig_num;
160 object *old_handler;
161 if (!getargs(args, "i", &sig_num))
162 return NULL;
163 if (sig_num < 1 || sig_num >= NSIG) {
164 err_setstr(ValueError, "signal number out of range");
165 return NULL;
166 }
167 old_handler = sig_list[sig_num].func;
168 INCREF(old_handler);
169 return old_handler;
170}
171
172
173/* List of functions defined in the module */
174
175static struct methodlist signal_methods[] = {
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000176 {"signal", signal_signal},
177 {"getsignal", signal_getsignal},
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000178 {NULL, NULL} /* sentinel */
179};
180
181void
182initsignal()
183{
184 object *m, *d, *x;
185 object *b_dict;
186 int i;
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000187
188#ifdef WITH_THREAD
189 main_thread = get_thread_ident();
190 main_pid = getpid();
191#endif
192
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000193 /* Create the module and add the functions */
194 m = initmodule("signal", signal_methods);
195
196 /* Add some symbolic constants to the module */
197 d = getmoduledict(m);
198
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000199 sig_dfl_object = newintobject((long)SIG_DFL);
200 dictinsert(d, "SIG_DFL", sig_dfl_object);
201 sig_ign_object = newintobject((long)SIG_IGN);
202 dictinsert(d, "SIG_IGN", sig_ign_object);
203 dictinsert(d, "NSIG", newintobject((long)NSIG));
204 default_int_handler_object = newmethodobject("default_int_handler",
205 default_int_handler,
206 (object *)NULL,
207 0);
208 dictinsert(d, "default_int_handler", default_int_handler_object);
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000209
210 sig_list[0].tripped = 0;
211 for (i = 1; i < NSIG; i++) {
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000212 RETSIGTYPE (*t)();
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000213 t = signal(i, SIG_IGN);
214 signal(i, t);
215 sig_list[i].tripped = 0;
216 if (t == SIG_DFL)
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000217 sig_list[i].func = sig_dfl_object;
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000218 else if (t == SIG_IGN)
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000219 sig_list[i].func = sig_ign_object;
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000220 else
221 sig_list[i].func = None; /* None of our business */
222 INCREF(sig_list[i].func);
223 }
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000224 if (sig_list[SIGINT].func == sig_dfl_object) {
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000225 /* Install default int handler */
226 DECREF(sig_list[SIGINT].func);
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000227 sig_list[SIGINT].func = default_int_handler_object;
228 INCREF(default_int_handler_object);
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000229 signal(SIGINT, &signal_handler);
230 }
231
232#ifdef SIGHUP
233 x = newintobject(SIGHUP);
234 dictinsert(d, "SIGHUP", x);
235#endif
236#ifdef SIGINT
237 x = newintobject(SIGINT);
238 dictinsert(d, "SIGINT", x);
239#endif
240#ifdef SIGQUIT
241 x = newintobject(SIGQUIT);
242 dictinsert(d, "SIGQUIT", x);
243#endif
244#ifdef SIGILL
245 x = newintobject(SIGILL);
246 dictinsert(d, "SIGILL", x);
247#endif
248#ifdef SIGTRAP
249 x = newintobject(SIGTRAP);
250 dictinsert(d, "SIGTRAP", x);
251#endif
252#ifdef SIGIOT
253 x = newintobject(SIGIOT);
254 dictinsert(d, "SIGIOT", x);
255#endif
256#ifdef SIGABRT
257 x = newintobject(SIGABRT);
258 dictinsert(d, "SIGABRT", x);
259#endif
260#ifdef SIGEMT
261 x = newintobject(SIGEMT);
262 dictinsert(d, "SIGEMT", x);
263#endif
264#ifdef SIGFPE
265 x = newintobject(SIGFPE);
266 dictinsert(d, "SIGFPE", x);
267#endif
268#ifdef SIGKILL
269 x = newintobject(SIGKILL);
270 dictinsert(d, "SIGKILL", x);
271#endif
272#ifdef SIGBUS
273 x = newintobject(SIGBUS);
274 dictinsert(d, "SIGBUS", x);
275#endif
276#ifdef SIGSEGV
277 x = newintobject(SIGSEGV);
278 dictinsert(d, "SIGSEGV", x);
279#endif
280#ifdef SIGSYS
281 x = newintobject(SIGSYS);
282 dictinsert(d, "SIGSYS", x);
283#endif
284#ifdef SIGPIPE
285 x = newintobject(SIGPIPE);
286 dictinsert(d, "SIGPIPE", x);
287#endif
288#ifdef SIGALRM
289 x = newintobject(SIGALRM);
290 dictinsert(d, "SIGALRM", x);
291#endif
292#ifdef SIGTERM
293 x = newintobject(SIGTERM);
294 dictinsert(d, "SIGTERM", x);
295#endif
296#ifdef SIGUSR1
297 x = newintobject(SIGUSR1);
298 dictinsert(d, "SIGUSR1", x);
299#endif
300#ifdef SIGUSR2
301 x = newintobject(SIGUSR2);
302 dictinsert(d, "SIGUSR2", x);
303#endif
304#ifdef SIGCLD
305 x = newintobject(SIGCLD);
306 dictinsert(d, "SIGCLD", x);
307#endif
308#ifdef SIGCHLD
309 x = newintobject(SIGCHLD);
310 dictinsert(d, "SIGCHLD", x);
311#endif
312#ifdef SIGPWR
313 x = newintobject(SIGPWR);
314 dictinsert(d, "SIGPWR", x);
315#endif
316#ifdef SIGIO
317 x = newintobject(SIGIO);
318 dictinsert(d, "SIGIO", x);
319#endif
320#ifdef SIGURG
321 x = newintobject(SIGURG);
322 dictinsert(d, "SIGURG", x);
323#endif
324#ifdef SIGWINCH
325 x = newintobject(SIGWINCH);
326 dictinsert(d, "SIGWINCH", x);
327#endif
328#ifdef SIGPOLL
329 x = newintobject(SIGPOLL);
330 dictinsert(d, "SIGPOLL", x);
331#endif
332#ifdef SIGSTOP
333 x = newintobject(SIGSTOP);
334 dictinsert(d, "SIGSTOP", x);
335#endif
336#ifdef SIGTSTP
337 x = newintobject(SIGTSTP);
338 dictinsert(d, "SIGTSTP", x);
339#endif
340#ifdef SIGCONT
341 x = newintobject(SIGCONT);
342 dictinsert(d, "SIGCONT", x);
343#endif
344#ifdef SIGTTIN
345 x = newintobject(SIGTTIN);
346 dictinsert(d, "SIGTTIN", x);
347#endif
348#ifdef SIGTTOU
349 x = newintobject(SIGTTOU);
350 dictinsert(d, "SIGTTOU", x);
351#endif
352#ifdef SIGVTALRM
353 x = newintobject(SIGVTALRM);
354 dictinsert(d, "SIGVTALRM", x);
355#endif
356#ifdef SIGPROF
357 x = newintobject(SIGPROF);
358 dictinsert(d, "SIGPROF", x);
359#endif
360#ifdef SIGCPU
361 x = newintobject(SIGCPU);
362 dictinsert(d, "SIGCPU", x);
363#endif
364#ifdef SIGFSZ
365 x = newintobject(SIGFSZ);
366 dictinsert(d, "SIGFSZ", x);
367#endif
368 /* Check for errors */
369 if (err_occurred())
370 fatal("can't initialize module signal");
371}
372
373int
374sigcheck()
375{
376 int i;
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000377 object *f;
378 if (!tripped)
379 return 0;
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000380#ifdef WITH_THREAD
381 if (get_thread_ident() != main_thread)
382 return 0;
383#endif
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000384 f = getframe();
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000385 if (f == NULL)
386 f = None;
387 for (i = 1; i < NSIG; i++) {
388 if (sig_list[i].tripped) {
389 object *arglist, *result;
390 sig_list[i].tripped = 0;
391 arglist = mkvalue("(iO)", i, f);
392 if (arglist == NULL)
393 result = NULL;
394 else {
395 result = call_object(sig_list[i].func,arglist);
396 DECREF(arglist);
397 }
398 if (result == NULL) {
399 return 1;
400 } else {
401 DECREF(result);
402 }
403 }
404 }
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000405 tripped = 0;
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000406 return 0;
407}
408
409/* Replacement for intrcheck.c functionality */
410
411void
412initintr()
413{
414 initsignal();
415}
416
417int
418intrcheck()
419{
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000420 if (sig_list[SIGINT].tripped) {
Guido van Rossumbb4ba121994-06-23 11:25:45 +0000421#ifdef WITH_THREAD
422 if (get_thread_ident() != main_thread)
423 return 0;
424#endif
Guido van Rossum6299d1e1994-05-31 12:51:13 +0000425 sig_list[SIGINT].tripped = 0;
426 return 1;
427 }
428 return 0;
Guido van Rossum398d9fe1994-05-11 08:59:13 +0000429}