2 /* Signal module -- many thanks to Lance Ellinghaus */
4 /* XXX Signals should be recorded per thread, now we have thread state. */
16 #define SIG_ERR ((PyOS_sighandler_t)(-1))
19 #if defined(PYOS_OS2) && !defined(PYCC_GCC)
26 # define NSIG _NSIG /* For BSD/SysV */
27 # elif defined(_SIGMAX)
28 # define NSIG (_SIGMAX + 1) /* For QNX */
29 # elif defined(SIGMAX)
30 # define NSIG (SIGMAX + 1) /* For djgpp */
32 # define NSIG 64 /* Use a reasonable default value */
38 NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS
40 When threads are supported, we want the following semantics:
42 - only the main thread can set a signal handler
43 - any thread can get a signal handler
44 - signals are only delivered to the main thread
46 I.e. we don't support "synchronous signals" like SIGFPE (catching
47 this doesn't make much sense in Python anyway) nor do we support
48 signals as a means of inter-thread communication, since not all
49 thread implementations support that (at least our thread library
52 We still have the problem that in some implementations signals
53 generated by the keyboard (e.g. SIGINT) are delivered to all
54 threads (e.g. SGI), while in others (e.g. Solaris) such signals are
55 delivered to one random thread (an intermediate possibility would
56 be to deliver it to the main thread -- POSIX?). For now, we have
57 a working implementation that works in all three cases -- the
58 handler ignores signals if getpid() isn't the same as in the main
59 thread. XXX This is a hack.
61 GNU pth is a user-space threading library, and as such, all threads
62 run within the same process. In this case, if the currently running
63 thread is not the main_thread, send the signal to the main_thread.
67 #include <sys/types.h> /* For pid_t */
69 static long main_thread
;
70 static pid_t main_pid
;
78 static int is_tripped
= 0; /* Speed up sigcheck() when none tripped */
80 static PyObject
*DefaultHandler
;
81 static PyObject
*IgnoreHandler
;
82 static PyObject
*IntHandler
;
84 /* On Solaris 8, gcc will produce a warning that the function
85 declaration is not a prototype. This is caused by the definition of
86 SIG_DFL as (void (*)())0; the correct declaration would have been
89 static PyOS_sighandler_t old_siginthandler
= SIG_DFL
;
93 signal_default_int_handler(PyObject
*self
, PyObject
*args
)
95 PyErr_SetNone(PyExc_KeyboardInterrupt
);
99 PyDoc_STRVAR(default_int_handler_doc
,
100 "default_int_handler(...)\n\
102 The default handler for SIGINT instated by Python.\n\
103 It raises KeyboardInterrupt.");
107 checksignals_witharg(void * unused
)
109 return PyErr_CheckSignals();
113 signal_handler(int sig_num
)
117 if (PyThread_get_thread_ident() != main_thread
) {
118 pth_raise(*(pth_t
*) main_thread
, sig_num
);
122 /* See NOTES section above */
123 if (getpid() == main_pid
) {
126 Handlers
[sig_num
].tripped
= 1;
127 Py_AddPendingCall(checksignals_witharg
, NULL
);
132 if (sig_num
== SIGCHLD
) {
133 /* To avoid infinite recursion, this signal remains
134 reset until explicit re-instated.
135 Don't clear the 'func' field as it is our pointer
136 to the Python handler... */
140 #ifdef HAVE_SIGINTERRUPT
141 siginterrupt(sig_num
, 1);
143 PyOS_setsig(sig_num
, signal_handler
);
149 signal_alarm(PyObject
*self
, PyObject
*args
)
152 if (!PyArg_ParseTuple(args
, "i:alarm", &t
))
154 /* alarm() returns the number of seconds remaining */
155 return PyInt_FromLong((long)alarm(t
));
158 PyDoc_STRVAR(alarm_doc
,
161 Arrange for SIGALRM to arrive after the given number of seconds.");
166 signal_pause(PyObject
*self
)
168 Py_BEGIN_ALLOW_THREADS
171 /* make sure that any exceptions that got raised are propagated
174 if (PyErr_CheckSignals())
180 PyDoc_STRVAR(pause_doc
,
183 Wait until a signal arrives.");
189 signal_signal(PyObject
*self
, PyObject
*args
)
193 PyObject
*old_handler
;
195 if (!PyArg_ParseTuple(args
, "iO:signal", &sig_num
, &obj
))
198 if (PyThread_get_thread_ident() != main_thread
) {
199 PyErr_SetString(PyExc_ValueError
,
200 "signal only works in main thread");
204 if (sig_num
< 1 || sig_num
>= NSIG
) {
205 PyErr_SetString(PyExc_ValueError
,
206 "signal number out of range");
209 if (obj
== IgnoreHandler
)
211 else if (obj
== DefaultHandler
)
213 else if (!PyCallable_Check(obj
)) {
214 PyErr_SetString(PyExc_TypeError
,
215 "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
219 func
= signal_handler
;
220 #ifdef HAVE_SIGINTERRUPT
221 siginterrupt(sig_num
, 1);
223 if (PyOS_setsig(sig_num
, func
) == SIG_ERR
) {
224 PyErr_SetFromErrno(PyExc_RuntimeError
);
227 old_handler
= Handlers
[sig_num
].func
;
228 Handlers
[sig_num
].tripped
= 0;
230 Handlers
[sig_num
].func
= obj
;
234 PyDoc_STRVAR(signal_doc
,
235 "signal(sig, action) -> action\n\
237 Set the action for the given signal. The action can be SIG_DFL,\n\
238 SIG_IGN, or a callable Python object. The previous action is\n\
239 returned. See getsignal() for possible return values.\n\
241 *** IMPORTANT NOTICE ***\n\
242 A signal handler function is called with two arguments:\n\
243 the first is the signal number, the second is the interrupted stack frame.");
247 signal_getsignal(PyObject
*self
, PyObject
*args
)
250 PyObject
*old_handler
;
251 if (!PyArg_ParseTuple(args
, "i:getsignal", &sig_num
))
253 if (sig_num
< 1 || sig_num
>= NSIG
) {
254 PyErr_SetString(PyExc_ValueError
,
255 "signal number out of range");
258 old_handler
= Handlers
[sig_num
].func
;
259 Py_INCREF(old_handler
);
263 PyDoc_STRVAR(getsignal_doc
,
264 "getsignal(sig) -> action\n\
266 Return the current action for the given signal. The return value can be:\n\
267 SIG_IGN -- if the signal is being ignored\n\
268 SIG_DFL -- if the default action for the signal is in effect\n\
269 None -- if an unknown handler is in effect\n\
270 anything else -- the callable Python object used as a handler");
272 #ifdef HAVE_SIGPROCMASK /* we assume that having SIGPROCMASK is enough
273 to guarantee full POSIX signal handling */
274 /* returns 0 for success, <0 for failure (with exception set) */
276 _signal_list_to_sigset(PyObject
* seq
, sigset_t
* set
, char* mesg
)
280 seq
= PySequence_Fast(seq
, mesg
);
284 len
= PySequence_Fast_GET_SIZE(seq
);
288 for (i
= 0; i
< len
; i
++) {
289 val
= PyInt_AsLong(PySequence_Fast_GET_ITEM(seq
, i
));
290 if (val
== -1 && PyErr_Occurred()) {
294 if (sigaddset(set
, val
) < 0) {
296 PyErr_SetFromErrno(PyExc_ValueError
);
306 _signal_sigset_to_list(sigset_t
* set
)
316 for (i
= 1; i
< NSIG
; i
++) {
317 if (sigismember(set
, i
)) {
318 ob
= PyInt_FromLong(i
);
323 PyList_Append(ret
, ob
);
332 signal_sigprocmask(PyObject
* self
, PyObject
* args
)
335 sigset_t newset
, oldset
;
338 if (!PyArg_ParseTuple(args
, "iO", &how
, &seq
))
341 if (_signal_list_to_sigset(seq
, &newset
,
342 "sigprocmask requires a sequence") < 0)
345 if (sigprocmask(how
, &newset
, &oldset
) < 0) {
346 return PyErr_SetFromErrno(PyExc_ValueError
);
349 if (PyErr_CheckSignals())
352 return _signal_sigset_to_list(&oldset
);
355 PyDoc_STRVAR(sigprocmask_doc
,
356 "sigprocmask(how, sigset) -> sigset\n\
358 Change the list of currently blocked signals. The parameter how should be\n\
359 one of SIG_BLOCK, SIG_UNBLOCK or SIG_SETMASK and sigset should be a\n\
360 sequence of signal numbers. The behaviour of the call depends on the value\n\
364 The set of blocked signals is the union of the current set and the\n\
367 The signals in sigset are removed from the current set of blocked\n\
368 signals. It is legal to attempt to unblock a signal which is not\n\
371 The set of blocked signals is set to the argument set.\n\
373 A list contating the numbers of the previously blocked signals is returned.");
376 signal_sigpending(PyObject
* self
)
380 if (sigpending(&set
) < 0) {
381 return PyErr_SetFromErrno(PyExc_ValueError
);
384 return _signal_sigset_to_list(&set
);
387 PyDoc_STRVAR(sigpending_doc
,
388 "sigpending() -> sigset\n\
390 Return the set of pending signals, i.e. a list containing the numbers of\n\
391 those signals that have been raised while blocked.");
394 signal_sigsuspend(PyObject
* self
, PyObject
* arg
)
398 if (_signal_list_to_sigset(arg
, &set
,
399 "sigsuspend requires a sequence") < 0)
402 Py_BEGIN_ALLOW_THREADS
406 if (PyErr_CheckSignals())
413 PyDoc_STRVAR(sigsuspend_doc
,
414 "sigsuspend(sigset) -> None\n\
416 Temporarily replace the signal mask with sigset (which should be a sequence\n\
417 of signal numbers) and suspend the process until a signal is received.");
420 /* List of functions defined in the module */
421 static PyMethodDef signal_methods
[] = {
423 {"alarm", signal_alarm
, METH_VARARGS
, alarm_doc
},
425 {"signal", signal_signal
, METH_VARARGS
, signal_doc
},
426 {"getsignal", signal_getsignal
, METH_VARARGS
, getsignal_doc
},
428 {"pause", (PyCFunction
)signal_pause
,
429 METH_NOARGS
,pause_doc
},
431 {"default_int_handler", signal_default_int_handler
,
432 METH_VARARGS
, default_int_handler_doc
},
433 #ifdef HAVE_SIGPROCMASK
434 {"sigprocmask", (PyCFunction
)signal_sigprocmask
,
435 METH_VARARGS
, sigprocmask_doc
},
436 {"sigpending", (PyCFunction
)signal_sigpending
,
437 METH_NOARGS
, sigpending_doc
},
438 {"sigsuspend", (PyCFunction
)signal_sigsuspend
,
439 METH_O
, sigsuspend_doc
},
441 {NULL
, NULL
} /* sentinel */
445 PyDoc_STRVAR(module_doc
,
446 "This module provides mechanisms to use signal handlers in Python.\n\
450 alarm() -- cause SIGALRM after a specified time [Unix only]\n\
451 signal() -- set the action for a given signal\n\
452 getsignal() -- get the signal action for a given signal\n\
453 pause() -- wait until a signal arrives [Unix only]\n\
454 default_int_handler() -- default SIGINT handler\n\
457 sigprocmask() |-- posix signal mask handling [Unix only]\n\
462 SIG_DFL -- used to refer to the system default handler\n\
463 SIG_IGN -- used to ignore the signal\n\
464 NSIG -- number of defined signals\n\
466 SIGINT, SIGTERM, etc. -- signal numbers\n\
468 *** IMPORTANT NOTICE ***\n\
469 A signal handler function is called with two arguments:\n\
470 the first is the signal number, the second is the interrupted stack frame.");
479 main_thread
= PyThread_get_thread_ident();
483 /* Create the module and add the functions */
484 m
= Py_InitModule3("signal", signal_methods
, module_doc
);
486 /* Add some symbolic constants to the module */
487 d
= PyModule_GetDict(m
);
489 x
= DefaultHandler
= PyLong_FromVoidPtr((void *)SIG_DFL
);
490 if (!x
|| PyDict_SetItemString(d
, "SIG_DFL", x
) < 0)
493 x
= IgnoreHandler
= PyLong_FromVoidPtr((void *)SIG_IGN
);
494 if (!x
|| PyDict_SetItemString(d
, "SIG_IGN", x
) < 0)
497 x
= PyInt_FromLong((long)NSIG
);
498 if (!x
|| PyDict_SetItemString(d
, "NSIG", x
) < 0)
502 x
= IntHandler
= PyDict_GetItemString(d
, "default_int_handler");
505 Py_INCREF(IntHandler
);
507 Handlers
[0].tripped
= 0;
508 for (i
= 1; i
< NSIG
; i
++) {
511 Handlers
[i
].tripped
= 0;
513 Handlers
[i
].func
= DefaultHandler
;
514 else if (t
== SIG_IGN
)
515 Handlers
[i
].func
= IgnoreHandler
;
517 Handlers
[i
].func
= Py_None
; /* None of our business */
518 Py_INCREF(Handlers
[i
].func
);
520 if (Handlers
[SIGINT
].func
== DefaultHandler
) {
521 /* Install default int handler */
522 Py_INCREF(IntHandler
);
523 Py_DECREF(Handlers
[SIGINT
].func
);
524 Handlers
[SIGINT
].func
= IntHandler
;
525 old_siginthandler
= PyOS_setsig(SIGINT
, signal_handler
);
529 x
= PyInt_FromLong(SIGHUP
);
530 PyDict_SetItemString(d
, "SIGHUP", x
);
534 x
= PyInt_FromLong(SIGINT
);
535 PyDict_SetItemString(d
, "SIGINT", x
);
539 x
= PyInt_FromLong(SIGBREAK
);
540 PyDict_SetItemString(d
, "SIGBREAK", x
);
544 x
= PyInt_FromLong(SIGQUIT
);
545 PyDict_SetItemString(d
, "SIGQUIT", x
);
549 x
= PyInt_FromLong(SIGILL
);
550 PyDict_SetItemString(d
, "SIGILL", x
);
554 x
= PyInt_FromLong(SIGTRAP
);
555 PyDict_SetItemString(d
, "SIGTRAP", x
);
559 x
= PyInt_FromLong(SIGIOT
);
560 PyDict_SetItemString(d
, "SIGIOT", x
);
564 x
= PyInt_FromLong(SIGABRT
);
565 PyDict_SetItemString(d
, "SIGABRT", x
);
569 x
= PyInt_FromLong(SIGEMT
);
570 PyDict_SetItemString(d
, "SIGEMT", x
);
574 x
= PyInt_FromLong(SIGFPE
);
575 PyDict_SetItemString(d
, "SIGFPE", x
);
579 x
= PyInt_FromLong(SIGKILL
);
580 PyDict_SetItemString(d
, "SIGKILL", x
);
584 x
= PyInt_FromLong(SIGBUS
);
585 PyDict_SetItemString(d
, "SIGBUS", x
);
589 x
= PyInt_FromLong(SIGSEGV
);
590 PyDict_SetItemString(d
, "SIGSEGV", x
);
594 x
= PyInt_FromLong(SIGSYS
);
595 PyDict_SetItemString(d
, "SIGSYS", x
);
599 x
= PyInt_FromLong(SIGPIPE
);
600 PyDict_SetItemString(d
, "SIGPIPE", x
);
604 x
= PyInt_FromLong(SIGALRM
);
605 PyDict_SetItemString(d
, "SIGALRM", x
);
609 x
= PyInt_FromLong(SIGTERM
);
610 PyDict_SetItemString(d
, "SIGTERM", x
);
614 x
= PyInt_FromLong(SIGUSR1
);
615 PyDict_SetItemString(d
, "SIGUSR1", x
);
619 x
= PyInt_FromLong(SIGUSR2
);
620 PyDict_SetItemString(d
, "SIGUSR2", x
);
624 x
= PyInt_FromLong(SIGCLD
);
625 PyDict_SetItemString(d
, "SIGCLD", x
);
629 x
= PyInt_FromLong(SIGCHLD
);
630 PyDict_SetItemString(d
, "SIGCHLD", x
);
634 x
= PyInt_FromLong(SIGPWR
);
635 PyDict_SetItemString(d
, "SIGPWR", x
);
639 x
= PyInt_FromLong(SIGIO
);
640 PyDict_SetItemString(d
, "SIGIO", x
);
644 x
= PyInt_FromLong(SIGURG
);
645 PyDict_SetItemString(d
, "SIGURG", x
);
649 x
= PyInt_FromLong(SIGWINCH
);
650 PyDict_SetItemString(d
, "SIGWINCH", x
);
654 x
= PyInt_FromLong(SIGPOLL
);
655 PyDict_SetItemString(d
, "SIGPOLL", x
);
659 x
= PyInt_FromLong(SIGSTOP
);
660 PyDict_SetItemString(d
, "SIGSTOP", x
);
664 x
= PyInt_FromLong(SIGTSTP
);
665 PyDict_SetItemString(d
, "SIGTSTP", x
);
669 x
= PyInt_FromLong(SIGCONT
);
670 PyDict_SetItemString(d
, "SIGCONT", x
);
674 x
= PyInt_FromLong(SIGTTIN
);
675 PyDict_SetItemString(d
, "SIGTTIN", x
);
679 x
= PyInt_FromLong(SIGTTOU
);
680 PyDict_SetItemString(d
, "SIGTTOU", x
);
684 x
= PyInt_FromLong(SIGVTALRM
);
685 PyDict_SetItemString(d
, "SIGVTALRM", x
);
689 x
= PyInt_FromLong(SIGPROF
);
690 PyDict_SetItemString(d
, "SIGPROF", x
);
694 x
= PyInt_FromLong(SIGXCPU
);
695 PyDict_SetItemString(d
, "SIGXCPU", x
);
699 x
= PyInt_FromLong(SIGXFSZ
);
700 PyDict_SetItemString(d
, "SIGXFSZ", x
);
704 x
= PyInt_FromLong(SIGINFO
);
705 PyDict_SetItemString(d
, "SIGINFO", x
);
708 #ifdef HAVE_SIGPROCMASK
709 x
= PyInt_FromLong(SIG_BLOCK
);
710 PyDict_SetItemString(d
, "SIG_BLOCK", x
);
712 x
= PyInt_FromLong(SIG_UNBLOCK
);
713 PyDict_SetItemString(d
, "SIG_UNBLOCK", x
);
715 x
= PyInt_FromLong(SIG_SETMASK
);
716 PyDict_SetItemString(d
, "SIG_SETMASK", x
);
720 if (!PyErr_Occurred())
723 /* Check for errors */
734 PyOS_setsig(SIGINT
, old_siginthandler
);
735 old_siginthandler
= SIG_DFL
;
737 for (i
= 1; i
< NSIG
; i
++) {
738 func
= Handlers
[i
].func
;
739 Handlers
[i
].tripped
= 0;
740 Handlers
[i
].func
= NULL
;
741 if (i
!= SIGINT
&& func
!= NULL
&& func
!= Py_None
&&
742 func
!= DefaultHandler
&& func
!= IgnoreHandler
)
743 PyOS_setsig(i
, SIG_DFL
);
747 Py_XDECREF(IntHandler
);
749 Py_XDECREF(DefaultHandler
);
750 DefaultHandler
= NULL
;
751 Py_XDECREF(IgnoreHandler
);
752 IgnoreHandler
= NULL
;
756 /* Declared in pyerrors.h */
758 PyErr_CheckSignals(void)
766 if (PyThread_get_thread_ident() != main_thread
)
769 if (!(f
= PyEval_GetFrame()))
772 for (i
= 1; i
< NSIG
; i
++) {
773 if (Handlers
[i
].tripped
) {
774 PyObject
*result
= NULL
;
775 PyObject
*arglist
= Py_BuildValue("(iO)", i
, f
);
776 Handlers
[i
].tripped
= 0;
779 result
= PyEval_CallObject(Handlers
[i
].func
,
794 /* Replacements for intrcheck.c functionality
795 * Declared in pyerrors.h
798 PyErr_SetInterrupt(void)
801 Handlers
[SIGINT
].tripped
= 1;
802 Py_AddPendingCall((int (*)(void *))PyErr_CheckSignals
, NULL
);
806 PyOS_InitInterrupts(void)
809 _PyImport_FixupExtension("signal", "signal");
813 PyOS_FiniInterrupts(void)
819 PyOS_InterruptOccurred(void)
821 if (Handlers
[SIGINT
].tripped
) {
823 if (PyThread_get_thread_ident() != main_thread
)
826 Handlers
[SIGINT
].tripped
= 0;
836 PyEval_ReInitThreads();
837 main_thread
= PyThread_get_thread_ident();