Ditched '_find_SET()', since it was a no-value-added wrapper around
[python/dscho.git] / Modules / signalmodule.c
blob26bb94050e75b7dfc8ed3dea194208c9a6ef55d4
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
15 permission.
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* Signal module -- many thanks to Lance Ellinghaus */
34 /* XXX Signals should be recorded per thread, now we have thread state. */
36 #include "Python.h"
37 #include "intrcheck.h"
39 #ifdef MS_WIN32
40 #include <process.h>
41 #endif
43 #ifdef HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
47 #include <signal.h>
49 #ifndef SIG_ERR
50 #define SIG_ERR ((RETSIGTYPE (*)())-1)
51 #endif
53 #if defined(PYOS_OS2)
54 #define NSIG 12
55 #include <process.h>
56 #endif
58 #ifndef NSIG
59 #ifdef _SIGMAX
60 #define NSIG (_SIGMAX + 1) /* For QNX */
61 #else
62 #define NSIG (SIGMAX + 1) /* for djgpp */
63 #endif
64 #endif
69 NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS
71 When threads are supported, we want the following semantics:
73 - only the main thread can set a signal handler
74 - any thread can get a signal handler
75 - signals are only delivered to the main thread
77 I.e. we don't support "synchronous signals" like SIGFPE (catching
78 this doesn't make much sense in Python anyway) nor do we support
79 signals as a means of inter-thread communication, since not all
80 thread implementations support that (at least our thread library
81 doesn't).
83 We still have the problem that in some implementations signals
84 generated by the keyboard (e.g. SIGINT) are delivered to all
85 threads (e.g. SGI), while in others (e.g. Solaris) such signals are
86 delivered to one random thread (an intermediate possibility would
87 be to deliver it to the main thread -- POSIX?). For now, we have
88 a working implementation that works in all three cases -- the
89 handler ignores signals if getpid() isn't the same as in the main
90 thread. XXX This is a hack.
94 #ifdef WITH_THREAD
95 #include <sys/types.h> /* For pid_t */
96 #include "pythread.h"
97 static long main_thread;
98 static pid_t main_pid;
99 #endif
101 static struct {
102 int tripped;
103 PyObject *func;
104 } Handlers[NSIG];
106 static int is_tripped = 0; /* Speed up sigcheck() when none tripped */
108 static PyObject *DefaultHandler;
109 static PyObject *IgnoreHandler;
110 static PyObject *IntHandler;
112 static RETSIGTYPE (*old_siginthandler)() = SIG_DFL;
116 static PyObject *
117 signal_default_int_handler(self, arg)
118 PyObject *self;
119 PyObject *arg;
121 PyErr_SetNone(PyExc_KeyboardInterrupt);
122 return NULL;
125 static char default_int_handler_doc[] =
126 "default_int_handler(...)\n\
128 The default handler for SIGINT instated by Python.\n\
129 It raises KeyboardInterrupt.";
132 static RETSIGTYPE
133 signal_handler(sig_num)
134 int sig_num;
136 #ifdef WITH_THREAD
137 /* See NOTES section above */
138 if (getpid() == main_pid) {
139 #endif
140 is_tripped++;
141 Handlers[sig_num].tripped = 1;
142 Py_AddPendingCall(
143 (int (*) Py_PROTO((ANY *)))PyErr_CheckSignals, NULL);
144 #ifdef WITH_THREAD
146 #endif
147 #ifdef SIGCHLD
148 if (sig_num == SIGCHLD) {
149 /* To avoid infinite recursion, this signal remains
150 reset until explicit re-instated.
151 Don't clear the 'func' field as it is our pointer
152 to the Python handler... */
153 return;
155 #endif
156 #ifdef HAVE_SIGINTERRUPT
157 siginterrupt(sig_num, 1);
158 #endif
159 (void)signal(sig_num, &signal_handler);
164 #ifdef HAVE_ALARM
165 static PyObject *
166 signal_alarm(self, args)
167 PyObject *self; /* Not used */
168 PyObject *args;
170 int t;
171 if (!PyArg_Parse(args, "i", &t))
172 return NULL;
173 /* alarm() returns the number of seconds remaining */
174 return PyInt_FromLong(alarm(t));
177 static char alarm_doc[] =
178 "alarm(seconds)\n\
180 Arrange for SIGALRM to arrive after the given number of seconds.";
181 #endif
183 #ifdef HAVE_PAUSE
184 static PyObject *
185 signal_pause(self, args)
186 PyObject *self; /* Not used */
187 PyObject *args;
189 if (!PyArg_NoArgs(args))
190 return NULL;
192 Py_BEGIN_ALLOW_THREADS
193 (void)pause();
194 Py_END_ALLOW_THREADS
195 /* make sure that any exceptions that got raised are propagated
196 * back into Python
198 if (PyErr_CheckSignals())
199 return NULL;
201 Py_INCREF(Py_None);
202 return Py_None;
204 static char pause_doc[] =
205 "pause()\n\
207 Wait until a signal arrives.";
209 #endif
212 static PyObject *
213 signal_signal(self, args)
214 PyObject *self; /* Not used */
215 PyObject *args;
217 PyObject *obj;
218 int sig_num;
219 PyObject *old_handler;
220 RETSIGTYPE (*func)();
221 if (!PyArg_Parse(args, "(iO)", &sig_num, &obj))
222 return NULL;
223 #ifdef WITH_THREAD
224 if (PyThread_get_thread_ident() != main_thread) {
225 PyErr_SetString(PyExc_ValueError,
226 "signal only works in main thread");
227 return NULL;
229 #endif
230 if (sig_num < 1 || sig_num >= NSIG) {
231 PyErr_SetString(PyExc_ValueError,
232 "signal number out of range");
233 return NULL;
235 if (obj == IgnoreHandler)
236 func = SIG_IGN;
237 else if (obj == DefaultHandler)
238 func = SIG_DFL;
239 else if (!PyCallable_Check(obj)) {
240 PyErr_SetString(PyExc_TypeError,
241 "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
242 return NULL;
244 else
245 func = signal_handler;
246 #ifdef HAVE_SIGINTERRUPT
247 siginterrupt(sig_num, 1);
248 #endif
249 if (signal(sig_num, func) == SIG_ERR) {
250 PyErr_SetFromErrno(PyExc_RuntimeError);
251 return NULL;
253 old_handler = Handlers[sig_num].func;
254 Handlers[sig_num].tripped = 0;
255 Py_INCREF(obj);
256 Handlers[sig_num].func = obj;
257 return old_handler;
260 static char signal_doc[] =
261 "signal(sig, action) -> action\n\
263 Set the action for the given signal. The action can be SIG_DFL,\n\
264 SIG_IGN, or a callable Python object. The previous action is\n\
265 returned. See getsignal() for possible return values.\n\
267 *** IMPORTANT NOTICE ***\n\
268 A signal handler function is called with two arguments:\n\
269 the first is the signal number, the second is the interrupted stack frame.";
272 static PyObject *
273 signal_getsignal(self, args)
274 PyObject *self; /* Not used */
275 PyObject *args;
277 int sig_num;
278 PyObject *old_handler;
279 if (!PyArg_Parse(args, "i", &sig_num))
280 return NULL;
281 if (sig_num < 1 || sig_num >= NSIG) {
282 PyErr_SetString(PyExc_ValueError,
283 "signal number out of range");
284 return NULL;
286 old_handler = Handlers[sig_num].func;
287 Py_INCREF(old_handler);
288 return old_handler;
291 static char getsignal_doc[] =
292 "getsignal(sig) -> action\n\
294 Return the current action for the given signal. The return value can be:\n\
295 SIG_IGN -- if the signal is being ignored\n\
296 SIG_DFL -- if the default action for the signal is in effect\n\
297 None -- if an unknown handler is in effect\n\
298 anything else -- the callable Python object used as a handler\n\
302 /* List of functions defined in the module */
303 static PyMethodDef signal_methods[] = {
304 #ifdef HAVE_ALARM
305 {"alarm", signal_alarm, 0, alarm_doc},
306 #endif
307 {"signal", signal_signal, 0, signal_doc},
308 {"getsignal", signal_getsignal, 0, getsignal_doc},
309 #ifdef HAVE_PAUSE
310 {"pause", signal_pause, 0, pause_doc},
311 #endif
312 {"default_int_handler", signal_default_int_handler, 0,
313 default_int_handler_doc},
314 {NULL, NULL} /* sentinel */
319 static char module_doc[] =
320 "This module provides mechanisms to use signal handlers in Python.\n\
322 Functions:\n\
324 alarm() -- cause SIGALRM after a specified time [Unix only]\n\
325 signal() -- set the action for a given signal\n\
326 getsignal() -- get the signal action for a given signal\n\
327 pause() -- wait until a signal arrives [Unix only]\n\
328 default_int_handler() -- default SIGINT handler\n\
330 Constants:\n\
332 SIG_DFL -- used to refer to the system default handler\n\
333 SIG_IGN -- used to ignore the signal\n\
334 NSIG -- number of defined signals\n\
336 SIGINT, SIGTERM, etc. -- signal numbers\n\
338 *** IMPORTANT NOTICE ***\n\
339 A signal handler function is called with two arguments:\n\
340 the first is the signal number, the second is the interrupted stack frame.";
342 DL_EXPORT(void)
343 initsignal()
345 PyObject *m, *d, *x;
346 int i;
348 #ifdef WITH_THREAD
349 main_thread = PyThread_get_thread_ident();
350 main_pid = getpid();
351 #endif
353 /* Create the module and add the functions */
354 m = Py_InitModule3("signal", signal_methods, module_doc);
356 /* Add some symbolic constants to the module */
357 d = PyModule_GetDict(m);
359 x = DefaultHandler = PyInt_FromLong((long)SIG_DFL);
360 if (!x || PyDict_SetItemString(d, "SIG_DFL", x) < 0)
361 goto finally;
363 x = IgnoreHandler = PyInt_FromLong((long)SIG_IGN);
364 if (!x || PyDict_SetItemString(d, "SIG_IGN", x) < 0)
365 goto finally;
367 x = PyInt_FromLong((long)NSIG);
368 if (!x || PyDict_SetItemString(d, "NSIG", x) < 0)
369 goto finally;
370 Py_DECREF(x);
372 x = IntHandler = PyDict_GetItemString(d, "default_int_handler");
373 if (!x)
374 goto finally;
375 Py_INCREF(IntHandler);
377 Handlers[0].tripped = 0;
378 for (i = 1; i < NSIG; i++) {
379 RETSIGTYPE (*t)();
380 #ifdef HAVE_SIGACTION
381 struct sigaction act;
382 sigaction(i, 0, &act);
383 t = act.sa_handler;
384 #else
385 t = signal(i, SIG_IGN);
386 signal(i, t);
387 #endif
388 Handlers[i].tripped = 0;
389 if (t == SIG_DFL)
390 Handlers[i].func = DefaultHandler;
391 else if (t == SIG_IGN)
392 Handlers[i].func = IgnoreHandler;
393 else
394 Handlers[i].func = Py_None; /* None of our business */
395 Py_INCREF(Handlers[i].func);
397 if (Handlers[SIGINT].func == DefaultHandler) {
398 /* Install default int handler */
399 Py_INCREF(IntHandler);
400 Py_DECREF(Handlers[SIGINT].func);
401 Handlers[SIGINT].func = IntHandler;
402 old_siginthandler = signal(SIGINT, &signal_handler);
405 #ifdef SIGHUP
406 x = PyInt_FromLong(SIGHUP);
407 PyDict_SetItemString(d, "SIGHUP", x);
408 Py_XDECREF(x);
409 #endif
410 #ifdef SIGINT
411 x = PyInt_FromLong(SIGINT);
412 PyDict_SetItemString(d, "SIGINT", x);
413 Py_XDECREF(x);
414 #endif
415 #ifdef SIGQUIT
416 x = PyInt_FromLong(SIGQUIT);
417 PyDict_SetItemString(d, "SIGQUIT", x);
418 Py_XDECREF(x);
419 #endif
420 #ifdef SIGILL
421 x = PyInt_FromLong(SIGILL);
422 PyDict_SetItemString(d, "SIGILL", x);
423 Py_XDECREF(x);
424 #endif
425 #ifdef SIGTRAP
426 x = PyInt_FromLong(SIGTRAP);
427 PyDict_SetItemString(d, "SIGTRAP", x);
428 Py_XDECREF(x);
429 #endif
430 #ifdef SIGIOT
431 x = PyInt_FromLong(SIGIOT);
432 PyDict_SetItemString(d, "SIGIOT", x);
433 Py_XDECREF(x);
434 #endif
435 #ifdef SIGABRT
436 x = PyInt_FromLong(SIGABRT);
437 PyDict_SetItemString(d, "SIGABRT", x);
438 Py_XDECREF(x);
439 #endif
440 #ifdef SIGEMT
441 x = PyInt_FromLong(SIGEMT);
442 PyDict_SetItemString(d, "SIGEMT", x);
443 Py_XDECREF(x);
444 #endif
445 #ifdef SIGFPE
446 x = PyInt_FromLong(SIGFPE);
447 PyDict_SetItemString(d, "SIGFPE", x);
448 Py_XDECREF(x);
449 #endif
450 #ifdef SIGKILL
451 x = PyInt_FromLong(SIGKILL);
452 PyDict_SetItemString(d, "SIGKILL", x);
453 Py_XDECREF(x);
454 #endif
455 #ifdef SIGBUS
456 x = PyInt_FromLong(SIGBUS);
457 PyDict_SetItemString(d, "SIGBUS", x);
458 Py_XDECREF(x);
459 #endif
460 #ifdef SIGSEGV
461 x = PyInt_FromLong(SIGSEGV);
462 PyDict_SetItemString(d, "SIGSEGV", x);
463 Py_XDECREF(x);
464 #endif
465 #ifdef SIGSYS
466 x = PyInt_FromLong(SIGSYS);
467 PyDict_SetItemString(d, "SIGSYS", x);
468 Py_XDECREF(x);
469 #endif
470 #ifdef SIGPIPE
471 x = PyInt_FromLong(SIGPIPE);
472 PyDict_SetItemString(d, "SIGPIPE", x);
473 Py_XDECREF(x);
474 #endif
475 #ifdef SIGALRM
476 x = PyInt_FromLong(SIGALRM);
477 PyDict_SetItemString(d, "SIGALRM", x);
478 Py_XDECREF(x);
479 #endif
480 #ifdef SIGTERM
481 x = PyInt_FromLong(SIGTERM);
482 PyDict_SetItemString(d, "SIGTERM", x);
483 Py_XDECREF(x);
484 #endif
485 #ifdef SIGUSR1
486 x = PyInt_FromLong(SIGUSR1);
487 PyDict_SetItemString(d, "SIGUSR1", x);
488 Py_XDECREF(x);
489 #endif
490 #ifdef SIGUSR2
491 x = PyInt_FromLong(SIGUSR2);
492 PyDict_SetItemString(d, "SIGUSR2", x);
493 Py_XDECREF(x);
494 #endif
495 #ifdef SIGCLD
496 x = PyInt_FromLong(SIGCLD);
497 PyDict_SetItemString(d, "SIGCLD", x);
498 Py_XDECREF(x);
499 #endif
500 #ifdef SIGCHLD
501 x = PyInt_FromLong(SIGCHLD);
502 PyDict_SetItemString(d, "SIGCHLD", x);
503 Py_XDECREF(x);
504 #endif
505 #ifdef SIGPWR
506 x = PyInt_FromLong(SIGPWR);
507 PyDict_SetItemString(d, "SIGPWR", x);
508 Py_XDECREF(x);
509 #endif
510 #ifdef SIGIO
511 x = PyInt_FromLong(SIGIO);
512 PyDict_SetItemString(d, "SIGIO", x);
513 Py_XDECREF(x);
514 #endif
515 #ifdef SIGURG
516 x = PyInt_FromLong(SIGURG);
517 PyDict_SetItemString(d, "SIGURG", x);
518 Py_XDECREF(x);
519 #endif
520 #ifdef SIGWINCH
521 x = PyInt_FromLong(SIGWINCH);
522 PyDict_SetItemString(d, "SIGWINCH", x);
523 Py_XDECREF(x);
524 #endif
525 #ifdef SIGPOLL
526 x = PyInt_FromLong(SIGPOLL);
527 PyDict_SetItemString(d, "SIGPOLL", x);
528 Py_XDECREF(x);
529 #endif
530 #ifdef SIGSTOP
531 x = PyInt_FromLong(SIGSTOP);
532 PyDict_SetItemString(d, "SIGSTOP", x);
533 Py_XDECREF(x);
534 #endif
535 #ifdef SIGTSTP
536 x = PyInt_FromLong(SIGTSTP);
537 PyDict_SetItemString(d, "SIGTSTP", x);
538 Py_XDECREF(x);
539 #endif
540 #ifdef SIGCONT
541 x = PyInt_FromLong(SIGCONT);
542 PyDict_SetItemString(d, "SIGCONT", x);
543 Py_XDECREF(x);
544 #endif
545 #ifdef SIGTTIN
546 x = PyInt_FromLong(SIGTTIN);
547 PyDict_SetItemString(d, "SIGTTIN", x);
548 Py_XDECREF(x);
549 #endif
550 #ifdef SIGTTOU
551 x = PyInt_FromLong(SIGTTOU);
552 PyDict_SetItemString(d, "SIGTTOU", x);
553 Py_XDECREF(x);
554 #endif
555 #ifdef SIGVTALRM
556 x = PyInt_FromLong(SIGVTALRM);
557 PyDict_SetItemString(d, "SIGVTALRM", x);
558 Py_XDECREF(x);
559 #endif
560 #ifdef SIGPROF
561 x = PyInt_FromLong(SIGPROF);
562 PyDict_SetItemString(d, "SIGPROF", x);
563 Py_XDECREF(x);
564 #endif
565 #ifdef SIGXCPU
566 x = PyInt_FromLong(SIGXCPU);
567 PyDict_SetItemString(d, "SIGXCPU", x);
568 Py_XDECREF(x);
569 #endif
570 #ifdef SIGXFSZ
571 x = PyInt_FromLong(SIGXFSZ);
572 PyDict_SetItemString(d, "SIGXFSZ", x);
573 Py_XDECREF(x);
574 #endif
575 if (!PyErr_Occurred())
576 return;
578 /* Check for errors */
579 finally:
580 return;
583 static void
584 finisignal()
586 int i;
587 PyObject *func;
589 signal(SIGINT, old_siginthandler);
590 old_siginthandler = SIG_DFL;
592 for (i = 1; i < NSIG; i++) {
593 func = Handlers[i].func;
594 Handlers[i].tripped = 0;
595 Handlers[i].func = NULL;
596 if (i != SIGINT && func != NULL && func != Py_None &&
597 func != DefaultHandler && func != IgnoreHandler)
598 signal(i, SIG_DFL);
599 Py_XDECREF(func);
602 Py_XDECREF(IntHandler);
603 IntHandler = NULL;
604 Py_XDECREF(DefaultHandler);
605 DefaultHandler = NULL;
606 Py_XDECREF(IgnoreHandler);
607 IgnoreHandler = NULL;
612 /* Declared in pyerrors.h */
614 PyErr_CheckSignals()
616 int i;
617 PyObject *f;
619 if (!is_tripped)
620 return 0;
621 #ifdef WITH_THREAD
622 if (PyThread_get_thread_ident() != main_thread)
623 return 0;
624 #endif
625 if (!(f = PyEval_GetFrame()))
626 f = Py_None;
628 for (i = 1; i < NSIG; i++) {
629 if (Handlers[i].tripped) {
630 PyObject *result = NULL;
631 PyObject *arglist = Py_BuildValue("(iO)", i, f);
632 Handlers[i].tripped = 0;
634 if (arglist) {
635 result = PyEval_CallObject(Handlers[i].func,
636 arglist);
637 Py_DECREF(arglist);
639 if (!result)
640 return -1;
642 Py_DECREF(result);
645 is_tripped = 0;
646 return 0;
650 /* Replacements for intrcheck.c functionality
651 * Declared in pyerrors.h
653 void
654 PyErr_SetInterrupt()
656 is_tripped++;
657 Handlers[SIGINT].tripped = 1;
658 Py_AddPendingCall((int (*) Py_PROTO((ANY *)))PyErr_CheckSignals, NULL);
661 void
662 PyOS_InitInterrupts()
664 initsignal();
665 _PyImport_FixupExtension("signal", "signal");
668 void
669 PyOS_FiniInterrupts()
671 finisignal();
675 PyOS_InterruptOccurred()
677 if (Handlers[SIGINT].tripped) {
678 #ifdef WITH_THREAD
679 if (PyThread_get_thread_ident() != main_thread)
680 return 0;
681 #endif
682 Handlers[SIGINT].tripped = 0;
683 return 1;
685 return 0;
688 void
689 PyOS_AfterFork()
691 #ifdef WITH_THREAD
692 main_thread = PyThread_get_thread_ident();
693 main_pid = getpid();
694 #endif