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 #ifdef HAVE_SIGINTERRUPT
157 siginterrupt(sig_num
, 1);
159 (void)signal(sig_num
, &signal_handler
);
166 signal_alarm(self
, args
)
167 PyObject
*self
; /* Not used */
171 if (!PyArg_Parse(args
, "i", &t
))
173 /* alarm() returns the number of seconds remaining */
174 return PyInt_FromLong(alarm(t
));
177 static char alarm_doc
[] =
180 Arrange for SIGALRM to arrive after the given number of seconds.";
185 signal_pause(self
, args
)
186 PyObject
*self
; /* Not used */
189 if (!PyArg_NoArgs(args
))
192 Py_BEGIN_ALLOW_THREADS
195 /* make sure that any exceptions that got raised are propagated
198 if (PyErr_CheckSignals())
204 static char pause_doc
[] =
207 Wait until a signal arrives.";
213 signal_signal(self
, args
)
214 PyObject
*self
; /* Not used */
219 PyObject
*old_handler
;
220 RETSIGTYPE (*func
)();
221 if (!PyArg_Parse(args
, "(iO)", &sig_num
, &obj
))
224 if (PyThread_get_thread_ident() != main_thread
) {
225 PyErr_SetString(PyExc_ValueError
,
226 "signal only works in main thread");
230 if (sig_num
< 1 || sig_num
>= NSIG
) {
231 PyErr_SetString(PyExc_ValueError
,
232 "signal number out of range");
235 if (obj
== IgnoreHandler
)
237 else if (obj
== DefaultHandler
)
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");
245 func
= signal_handler
;
246 #ifdef HAVE_SIGINTERRUPT
247 siginterrupt(sig_num
, 1);
249 if (signal(sig_num
, func
) == SIG_ERR
) {
250 PyErr_SetFromErrno(PyExc_RuntimeError
);
253 old_handler
= Handlers
[sig_num
].func
;
254 Handlers
[sig_num
].tripped
= 0;
256 Handlers
[sig_num
].func
= obj
;
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.";
273 signal_getsignal(self
, args
)
274 PyObject
*self
; /* Not used */
278 PyObject
*old_handler
;
279 if (!PyArg_Parse(args
, "i", &sig_num
))
281 if (sig_num
< 1 || sig_num
>= NSIG
) {
282 PyErr_SetString(PyExc_ValueError
,
283 "signal number out of range");
286 old_handler
= Handlers
[sig_num
].func
;
287 Py_INCREF(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
[] = {
305 {"alarm", signal_alarm
, 0, alarm_doc
},
307 {"signal", signal_signal
, 0, signal_doc
},
308 {"getsignal", signal_getsignal
, 0, getsignal_doc
},
310 {"pause", signal_pause
, 0, pause_doc
},
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\
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\
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.";
349 main_thread
= PyThread_get_thread_ident();
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)
363 x
= IgnoreHandler
= PyInt_FromLong((long)SIG_IGN
);
364 if (!x
|| PyDict_SetItemString(d
, "SIG_IGN", x
) < 0)
367 x
= PyInt_FromLong((long)NSIG
);
368 if (!x
|| PyDict_SetItemString(d
, "NSIG", x
) < 0)
372 x
= IntHandler
= PyDict_GetItemString(d
, "default_int_handler");
375 Py_INCREF(IntHandler
);
377 Handlers
[0].tripped
= 0;
378 for (i
= 1; i
< NSIG
; i
++) {
380 #ifdef HAVE_SIGACTION
381 struct sigaction act
;
382 sigaction(i
, 0, &act
);
385 t
= signal(i
, SIG_IGN
);
388 Handlers
[i
].tripped
= 0;
390 Handlers
[i
].func
= DefaultHandler
;
391 else if (t
== SIG_IGN
)
392 Handlers
[i
].func
= IgnoreHandler
;
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
);
406 x
= PyInt_FromLong(SIGHUP
);
407 PyDict_SetItemString(d
, "SIGHUP", x
);
411 x
= PyInt_FromLong(SIGINT
);
412 PyDict_SetItemString(d
, "SIGINT", x
);
416 x
= PyInt_FromLong(SIGQUIT
);
417 PyDict_SetItemString(d
, "SIGQUIT", x
);
421 x
= PyInt_FromLong(SIGILL
);
422 PyDict_SetItemString(d
, "SIGILL", x
);
426 x
= PyInt_FromLong(SIGTRAP
);
427 PyDict_SetItemString(d
, "SIGTRAP", x
);
431 x
= PyInt_FromLong(SIGIOT
);
432 PyDict_SetItemString(d
, "SIGIOT", x
);
436 x
= PyInt_FromLong(SIGABRT
);
437 PyDict_SetItemString(d
, "SIGABRT", x
);
441 x
= PyInt_FromLong(SIGEMT
);
442 PyDict_SetItemString(d
, "SIGEMT", x
);
446 x
= PyInt_FromLong(SIGFPE
);
447 PyDict_SetItemString(d
, "SIGFPE", x
);
451 x
= PyInt_FromLong(SIGKILL
);
452 PyDict_SetItemString(d
, "SIGKILL", x
);
456 x
= PyInt_FromLong(SIGBUS
);
457 PyDict_SetItemString(d
, "SIGBUS", x
);
461 x
= PyInt_FromLong(SIGSEGV
);
462 PyDict_SetItemString(d
, "SIGSEGV", x
);
466 x
= PyInt_FromLong(SIGSYS
);
467 PyDict_SetItemString(d
, "SIGSYS", x
);
471 x
= PyInt_FromLong(SIGPIPE
);
472 PyDict_SetItemString(d
, "SIGPIPE", x
);
476 x
= PyInt_FromLong(SIGALRM
);
477 PyDict_SetItemString(d
, "SIGALRM", x
);
481 x
= PyInt_FromLong(SIGTERM
);
482 PyDict_SetItemString(d
, "SIGTERM", x
);
486 x
= PyInt_FromLong(SIGUSR1
);
487 PyDict_SetItemString(d
, "SIGUSR1", x
);
491 x
= PyInt_FromLong(SIGUSR2
);
492 PyDict_SetItemString(d
, "SIGUSR2", x
);
496 x
= PyInt_FromLong(SIGCLD
);
497 PyDict_SetItemString(d
, "SIGCLD", x
);
501 x
= PyInt_FromLong(SIGCHLD
);
502 PyDict_SetItemString(d
, "SIGCHLD", x
);
506 x
= PyInt_FromLong(SIGPWR
);
507 PyDict_SetItemString(d
, "SIGPWR", x
);
511 x
= PyInt_FromLong(SIGIO
);
512 PyDict_SetItemString(d
, "SIGIO", x
);
516 x
= PyInt_FromLong(SIGURG
);
517 PyDict_SetItemString(d
, "SIGURG", x
);
521 x
= PyInt_FromLong(SIGWINCH
);
522 PyDict_SetItemString(d
, "SIGWINCH", x
);
526 x
= PyInt_FromLong(SIGPOLL
);
527 PyDict_SetItemString(d
, "SIGPOLL", x
);
531 x
= PyInt_FromLong(SIGSTOP
);
532 PyDict_SetItemString(d
, "SIGSTOP", x
);
536 x
= PyInt_FromLong(SIGTSTP
);
537 PyDict_SetItemString(d
, "SIGTSTP", x
);
541 x
= PyInt_FromLong(SIGCONT
);
542 PyDict_SetItemString(d
, "SIGCONT", x
);
546 x
= PyInt_FromLong(SIGTTIN
);
547 PyDict_SetItemString(d
, "SIGTTIN", x
);
551 x
= PyInt_FromLong(SIGTTOU
);
552 PyDict_SetItemString(d
, "SIGTTOU", x
);
556 x
= PyInt_FromLong(SIGVTALRM
);
557 PyDict_SetItemString(d
, "SIGVTALRM", x
);
561 x
= PyInt_FromLong(SIGPROF
);
562 PyDict_SetItemString(d
, "SIGPROF", x
);
566 x
= PyInt_FromLong(SIGXCPU
);
567 PyDict_SetItemString(d
, "SIGXCPU", x
);
571 x
= PyInt_FromLong(SIGXFSZ
);
572 PyDict_SetItemString(d
, "SIGXFSZ", x
);
575 if (!PyErr_Occurred())
578 /* Check for errors */
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
)
602 Py_XDECREF(IntHandler
);
604 Py_XDECREF(DefaultHandler
);
605 DefaultHandler
= NULL
;
606 Py_XDECREF(IgnoreHandler
);
607 IgnoreHandler
= NULL
;
612 /* Declared in pyerrors.h */
622 if (PyThread_get_thread_ident() != main_thread
)
625 if (!(f
= PyEval_GetFrame()))
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;
635 result
= PyEval_CallObject(Handlers
[i
].func
,
650 /* Replacements for intrcheck.c functionality
651 * Declared in pyerrors.h
657 Handlers
[SIGINT
].tripped
= 1;
658 Py_AddPendingCall((int (*) Py_PROTO((ANY
*)))PyErr_CheckSignals
, NULL
);
662 PyOS_InitInterrupts()
665 _PyImport_FixupExtension("signal", "signal");
669 PyOS_FiniInterrupts()
675 PyOS_InterruptOccurred()
677 if (Handlers
[SIGINT
].tripped
) {
679 if (PyThread_get_thread_ident() != main_thread
)
682 Handlers
[SIGINT
].tripped
= 0;
692 main_thread
= PyThread_get_thread_ident();