1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
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
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. */
37 #include "intrcheck.h"
50 #define SIG_ERR ((RETSIGTYPE (*)())-1)
60 #define NSIG (_SIGMAX + 1) /* For QNX */
62 #define NSIG (SIGMAX + 1) /* for djgpp */
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
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.
95 #include <sys/types.h> /* For pid_t */
97 static long main_thread
;
98 static pid_t main_pid
;
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
;
117 signal_default_int_handler(self
, arg
)
121 PyErr_SetNone(PyExc_KeyboardInterrupt
);
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.";
133 signal_handler(sig_num
)
137 /* See NOTES section above */
138 if (getpid() == main_pid
) {
141 Handlers
[sig_num
].tripped
= 1;
143 (int (*) Py_PROTO((ANY
*)))PyErr_CheckSignals
, NULL
);
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... */
156 (void)signal(sig_num
, &signal_handler
);
163 signal_alarm(self
, args
)
164 PyObject
*self
; /* Not used */
168 if (!PyArg_Parse(args
, "i", &t
))
170 /* alarm() returns the number of seconds remaining */
171 return PyInt_FromLong(alarm(t
));
174 static char alarm_doc
[] =
177 Arrange for SIGALRM to arrive after the given number of seconds.";
182 signal_pause(self
, args
)
183 PyObject
*self
; /* Not used */
186 if (!PyArg_NoArgs(args
))
189 Py_BEGIN_ALLOW_THREADS
192 /* make sure that any exceptions that got raised are propagated
195 if (PyErr_CheckSignals())
201 static char pause_doc
[] =
204 Wait until a signal arrives.";
210 signal_signal(self
, args
)
211 PyObject
*self
; /* Not used */
216 PyObject
*old_handler
;
217 RETSIGTYPE (*func
)();
218 if (!PyArg_Parse(args
, "(iO)", &sig_num
, &obj
))
221 if (get_thread_ident() != main_thread
) {
222 PyErr_SetString(PyExc_ValueError
,
223 "signal only works in main thread");
227 if (sig_num
< 1 || sig_num
>= NSIG
) {
228 PyErr_SetString(PyExc_ValueError
,
229 "signal number out of range");
232 if (obj
== IgnoreHandler
)
234 else if (obj
== DefaultHandler
)
236 else if (!PyCallable_Check(obj
)) {
237 PyErr_SetString(PyExc_TypeError
,
238 "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
242 func
= signal_handler
;
243 if (signal(sig_num
, func
) == SIG_ERR
) {
244 PyErr_SetFromErrno(PyExc_RuntimeError
);
247 old_handler
= Handlers
[sig_num
].func
;
248 Handlers
[sig_num
].tripped
= 0;
250 Handlers
[sig_num
].func
= obj
;
254 static char signal_doc
[] =
255 "signal(sig, action) -> action\n\
257 Set the action for the given signal. The action can be SIG_DFL,\n\
258 SIG_IGN, or a callable Python object. The previous action is\n\
259 returned. See getsignal() for possible return values.\n\
261 *** IMPORTANT NOTICE ***\n\
262 A signal handler function is called with two arguments:\n\
263 the first is the signal number, the second is the interrupted stack frame.";
267 signal_getsignal(self
, args
)
268 PyObject
*self
; /* Not used */
272 PyObject
*old_handler
;
273 if (!PyArg_Parse(args
, "i", &sig_num
))
275 if (sig_num
< 1 || sig_num
>= NSIG
) {
276 PyErr_SetString(PyExc_ValueError
,
277 "signal number out of range");
280 old_handler
= Handlers
[sig_num
].func
;
281 Py_INCREF(old_handler
);
285 static char getsignal_doc
[] =
286 "getsignal(sig) -> action\n\
288 Return the current action for the given signal. The return value can be:\n\
289 SIG_IGN -- if the signal is being ignored\n\
290 SIG_DFL -- if the default action for the signal is in effect\n\
291 None -- if an unknown handler is in effect\n\
292 anything else -- the callable Python object used as a handler\n\
296 /* List of functions defined in the module */
297 static PyMethodDef signal_methods
[] = {
299 {"alarm", signal_alarm
, 0, alarm_doc
},
301 {"signal", signal_signal
, 0, signal_doc
},
302 {"getsignal", signal_getsignal
, 0, getsignal_doc
},
304 {"pause", signal_pause
, 0, pause_doc
},
306 {"default_int_handler", signal_default_int_handler
, 0,
307 default_int_handler_doc
},
308 {NULL
, NULL
} /* sentinel */
313 static char module_doc
[] =
314 "This module provides mechanisms to use signal handlers in Python.\n\
318 alarm() -- cause SIGALRM after a specified time [Unix only]\n\
319 signal() -- set the action for a given signal\n\
320 getsignal() -- get the signal action for a given signal\n\
321 pause() -- wait until a signal arrives [Unix only]\n\
322 default_int_handler() -- default SIGINT handler\n\
326 SIG_DFL -- used to refer to the system default handler\n\
327 SIG_IGN -- used to ignore the signal\n\
328 NSIG -- number of defined signals\n\
330 SIGINT, SIGTERM, etc. -- signal numbers\n\
332 *** IMPORTANT NOTICE ***\n\
333 A signal handler function is called with two arguments:\n\
334 the first is the signal number, the second is the interrupted stack frame.";
343 main_thread
= get_thread_ident();
347 /* Create the module and add the functions */
348 m
= Py_InitModule3("signal", signal_methods
, module_doc
);
350 /* Add some symbolic constants to the module */
351 d
= PyModule_GetDict(m
);
353 x
= DefaultHandler
= PyInt_FromLong((long)SIG_DFL
);
354 if (!x
|| PyDict_SetItemString(d
, "SIG_DFL", x
) < 0)
357 x
= IgnoreHandler
= PyInt_FromLong((long)SIG_IGN
);
358 if (!x
|| PyDict_SetItemString(d
, "SIG_IGN", x
) < 0)
361 x
= PyInt_FromLong((long)NSIG
);
362 if (!x
|| PyDict_SetItemString(d
, "NSIG", x
) < 0)
366 x
= IntHandler
= PyDict_GetItemString(d
, "default_int_handler");
369 Py_INCREF(IntHandler
);
371 Handlers
[0].tripped
= 0;
372 for (i
= 1; i
< NSIG
; i
++) {
374 #ifdef HAVE_SIGACTION
375 struct sigaction act
;
376 sigaction(i
, 0, &act
);
379 t
= signal(i
, SIG_IGN
);
382 Handlers
[i
].tripped
= 0;
384 Handlers
[i
].func
= DefaultHandler
;
385 else if (t
== SIG_IGN
)
386 Handlers
[i
].func
= IgnoreHandler
;
388 Handlers
[i
].func
= Py_None
; /* None of our business */
389 Py_INCREF(Handlers
[i
].func
);
391 if (Handlers
[SIGINT
].func
== DefaultHandler
) {
392 /* Install default int handler */
393 Py_INCREF(IntHandler
);
394 Py_DECREF(Handlers
[SIGINT
].func
);
395 Handlers
[SIGINT
].func
= IntHandler
;
396 old_siginthandler
= signal(SIGINT
, &signal_handler
);
400 x
= PyInt_FromLong(SIGHUP
);
401 PyDict_SetItemString(d
, "SIGHUP", x
);
405 x
= PyInt_FromLong(SIGINT
);
406 PyDict_SetItemString(d
, "SIGINT", x
);
410 x
= PyInt_FromLong(SIGQUIT
);
411 PyDict_SetItemString(d
, "SIGQUIT", x
);
415 x
= PyInt_FromLong(SIGILL
);
416 PyDict_SetItemString(d
, "SIGILL", x
);
420 x
= PyInt_FromLong(SIGTRAP
);
421 PyDict_SetItemString(d
, "SIGTRAP", x
);
425 x
= PyInt_FromLong(SIGIOT
);
426 PyDict_SetItemString(d
, "SIGIOT", x
);
430 x
= PyInt_FromLong(SIGABRT
);
431 PyDict_SetItemString(d
, "SIGABRT", x
);
435 x
= PyInt_FromLong(SIGEMT
);
436 PyDict_SetItemString(d
, "SIGEMT", x
);
440 x
= PyInt_FromLong(SIGFPE
);
441 PyDict_SetItemString(d
, "SIGFPE", x
);
445 x
= PyInt_FromLong(SIGKILL
);
446 PyDict_SetItemString(d
, "SIGKILL", x
);
450 x
= PyInt_FromLong(SIGBUS
);
451 PyDict_SetItemString(d
, "SIGBUS", x
);
455 x
= PyInt_FromLong(SIGSEGV
);
456 PyDict_SetItemString(d
, "SIGSEGV", x
);
460 x
= PyInt_FromLong(SIGSYS
);
461 PyDict_SetItemString(d
, "SIGSYS", x
);
465 x
= PyInt_FromLong(SIGPIPE
);
466 PyDict_SetItemString(d
, "SIGPIPE", x
);
470 x
= PyInt_FromLong(SIGALRM
);
471 PyDict_SetItemString(d
, "SIGALRM", x
);
475 x
= PyInt_FromLong(SIGTERM
);
476 PyDict_SetItemString(d
, "SIGTERM", x
);
480 x
= PyInt_FromLong(SIGUSR1
);
481 PyDict_SetItemString(d
, "SIGUSR1", x
);
485 x
= PyInt_FromLong(SIGUSR2
);
486 PyDict_SetItemString(d
, "SIGUSR2", x
);
490 x
= PyInt_FromLong(SIGCLD
);
491 PyDict_SetItemString(d
, "SIGCLD", x
);
495 x
= PyInt_FromLong(SIGCHLD
);
496 PyDict_SetItemString(d
, "SIGCHLD", x
);
500 x
= PyInt_FromLong(SIGPWR
);
501 PyDict_SetItemString(d
, "SIGPWR", x
);
505 x
= PyInt_FromLong(SIGIO
);
506 PyDict_SetItemString(d
, "SIGIO", x
);
510 x
= PyInt_FromLong(SIGURG
);
511 PyDict_SetItemString(d
, "SIGURG", x
);
515 x
= PyInt_FromLong(SIGWINCH
);
516 PyDict_SetItemString(d
, "SIGWINCH", x
);
520 x
= PyInt_FromLong(SIGPOLL
);
521 PyDict_SetItemString(d
, "SIGPOLL", x
);
525 x
= PyInt_FromLong(SIGSTOP
);
526 PyDict_SetItemString(d
, "SIGSTOP", x
);
530 x
= PyInt_FromLong(SIGTSTP
);
531 PyDict_SetItemString(d
, "SIGTSTP", x
);
535 x
= PyInt_FromLong(SIGCONT
);
536 PyDict_SetItemString(d
, "SIGCONT", x
);
540 x
= PyInt_FromLong(SIGTTIN
);
541 PyDict_SetItemString(d
, "SIGTTIN", x
);
545 x
= PyInt_FromLong(SIGTTOU
);
546 PyDict_SetItemString(d
, "SIGTTOU", x
);
550 x
= PyInt_FromLong(SIGVTALRM
);
551 PyDict_SetItemString(d
, "SIGVTALRM", x
);
555 x
= PyInt_FromLong(SIGPROF
);
556 PyDict_SetItemString(d
, "SIGPROF", x
);
560 x
= PyInt_FromLong(SIGXCPU
);
561 PyDict_SetItemString(d
, "SIGXCPU", x
);
565 x
= PyInt_FromLong(SIGXFSZ
);
566 PyDict_SetItemString(d
, "SIGXFSZ", x
);
569 if (!PyErr_Occurred())
572 /* Check for errors */
583 signal(SIGINT
, old_siginthandler
);
584 old_siginthandler
= SIG_DFL
;
586 for (i
= 1; i
< NSIG
; i
++) {
587 func
= Handlers
[i
].func
;
588 Handlers
[i
].tripped
= 0;
589 Handlers
[i
].func
= NULL
;
590 if (i
!= SIGINT
&& func
!= NULL
&& func
!= Py_None
&&
591 func
!= DefaultHandler
&& func
!= IgnoreHandler
)
596 Py_XDECREF(IntHandler
);
598 Py_XDECREF(DefaultHandler
);
599 DefaultHandler
= NULL
;
600 Py_XDECREF(IgnoreHandler
);
601 IgnoreHandler
= NULL
;
606 /* Declared in pyerrors.h */
616 if (get_thread_ident() != main_thread
)
619 if (!(f
= PyEval_GetFrame()))
622 for (i
= 1; i
< NSIG
; i
++) {
623 if (Handlers
[i
].tripped
) {
624 PyObject
*result
= NULL
;
625 PyObject
*arglist
= Py_BuildValue("(iO)", i
, f
);
626 Handlers
[i
].tripped
= 0;
629 result
= PyEval_CallObject(Handlers
[i
].func
,
644 /* Replacements for intrcheck.c functionality
645 * Declared in pyerrors.h
651 Handlers
[SIGINT
].tripped
= 1;
652 Py_AddPendingCall((int (*) Py_PROTO((ANY
*)))PyErr_CheckSignals
, NULL
);
656 PyOS_InitInterrupts()
659 _PyImport_FixupExtension("signal", "signal");
663 PyOS_FiniInterrupts()
669 PyOS_InterruptOccurred()
671 if (Handlers
[SIGINT
].tripped
) {
673 if (get_thread_ident() != main_thread
)
676 Handlers
[SIGINT
].tripped
= 0;
686 main_thread
= get_thread_ident();