2 /* Signal module -- many thanks to Lance Ellinghaus */
4 /* XXX Signals should be recorded per thread, now we have thread state. */
18 #define SIG_ERR ((PyOS_sighandler_t)(-1))
21 #if defined(PYOS_OS2) && !defined(PYCC_GCC)
28 # define NSIG _NSIG /* For BSD/SysV */
29 # elif defined(_SIGMAX)
30 # define NSIG (_SIGMAX + 1) /* For QNX */
31 # elif defined(SIGMAX)
32 # define NSIG (SIGMAX + 1) /* For djgpp */
34 # define NSIG 64 /* Use a reasonable default value */
40 NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS
42 When threads are supported, we want the following semantics:
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
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
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.
63 GNU pth is a user-space threading library, and as such, all threads
64 run within the same process. In this case, if the currently running
65 thread is not the main_thread, send the signal to the main_thread.
69 #include <sys/types.h> /* For pid_t */
71 static long main_thread
;
72 static pid_t main_pid
;
80 static sig_atomic_t wakeup_fd
= -1;
82 /* Speed up sigcheck() when none tripped */
83 static volatile sig_atomic_t is_tripped
= 0;
85 static PyObject
*DefaultHandler
;
86 static PyObject
*IgnoreHandler
;
87 static PyObject
*IntHandler
;
89 /* On Solaris 8, gcc will produce a warning that the function
90 declaration is not a prototype. This is caused by the definition of
91 SIG_DFL as (void (*)())0; the correct declaration would have been
94 static PyOS_sighandler_t old_siginthandler
= SIG_DFL
;
98 signal_default_int_handler(PyObject
*self
, PyObject
*args
)
100 PyErr_SetNone(PyExc_KeyboardInterrupt
);
104 PyDoc_STRVAR(default_int_handler_doc
,
105 "default_int_handler(...)\n\
107 The default handler for SIGINT installed by Python.\n\
108 It raises KeyboardInterrupt.");
112 checksignals_witharg(void * unused
)
114 return PyErr_CheckSignals();
118 signal_handler(int sig_num
)
122 if (PyThread_get_thread_ident() != main_thread
) {
123 pth_raise(*(pth_t
*) main_thread
, sig_num
);
127 /* See NOTES section above */
128 if (getpid() == main_pid
) {
130 Handlers
[sig_num
].tripped
= 1;
131 /* Set is_tripped after setting .tripped, as it gets
132 cleared in PyErr_CheckSignals() before .tripped. */
134 Py_AddPendingCall(checksignals_witharg
, NULL
);
136 write(wakeup_fd
, "\0", 1);
141 if (sig_num
== SIGCHLD
) {
142 /* To avoid infinite recursion, this signal remains
143 reset until explicit re-instated.
144 Don't clear the 'func' field as it is our pointer
145 to the Python handler... */
149 PyOS_setsig(sig_num
, signal_handler
);
155 signal_alarm(PyObject
*self
, PyObject
*args
)
158 if (!PyArg_ParseTuple(args
, "i:alarm", &t
))
160 /* alarm() returns the number of seconds remaining */
161 return PyInt_FromLong((long)alarm(t
));
164 PyDoc_STRVAR(alarm_doc
,
167 Arrange for SIGALRM to arrive after the given number of seconds.");
172 signal_pause(PyObject
*self
)
174 Py_BEGIN_ALLOW_THREADS
177 /* make sure that any exceptions that got raised are propagated
180 if (PyErr_CheckSignals())
186 PyDoc_STRVAR(pause_doc
,
189 Wait until a signal arrives.");
195 signal_signal(PyObject
*self
, PyObject
*args
)
199 PyObject
*old_handler
;
201 if (!PyArg_ParseTuple(args
, "iO:signal", &sig_num
, &obj
))
204 if (PyThread_get_thread_ident() != main_thread
) {
205 PyErr_SetString(PyExc_ValueError
,
206 "signal only works in main thread");
210 if (sig_num
< 1 || sig_num
>= NSIG
) {
211 PyErr_SetString(PyExc_ValueError
,
212 "signal number out of range");
215 if (obj
== IgnoreHandler
)
217 else if (obj
== DefaultHandler
)
219 else if (!PyCallable_Check(obj
)) {
220 PyErr_SetString(PyExc_TypeError
,
221 "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
225 func
= signal_handler
;
226 if (PyOS_setsig(sig_num
, func
) == SIG_ERR
) {
227 PyErr_SetFromErrno(PyExc_RuntimeError
);
230 old_handler
= Handlers
[sig_num
].func
;
231 Handlers
[sig_num
].tripped
= 0;
233 Handlers
[sig_num
].func
= obj
;
237 PyDoc_STRVAR(signal_doc
,
238 "signal(sig, action) -> action\n\
240 Set the action for the given signal. The action can be SIG_DFL,\n\
241 SIG_IGN, or a callable Python object. The previous action is\n\
242 returned. See getsignal() for possible return values.\n\
244 *** IMPORTANT NOTICE ***\n\
245 A signal handler function is called with two arguments:\n\
246 the first is the signal number, the second is the interrupted stack frame.");
250 signal_getsignal(PyObject
*self
, PyObject
*args
)
253 PyObject
*old_handler
;
254 if (!PyArg_ParseTuple(args
, "i:getsignal", &sig_num
))
256 if (sig_num
< 1 || sig_num
>= NSIG
) {
257 PyErr_SetString(PyExc_ValueError
,
258 "signal number out of range");
261 old_handler
= Handlers
[sig_num
].func
;
262 Py_INCREF(old_handler
);
266 PyDoc_STRVAR(getsignal_doc
,
267 "getsignal(sig) -> action\n\
269 Return the current action for the given signal. The return value can be:\n\
270 SIG_IGN -- if the signal is being ignored\n\
271 SIG_DFL -- if the default action for the signal is in effect\n\
272 None -- if an unknown handler is in effect\n\
273 anything else -- the callable Python object used as a handler");
277 signal_set_wakeup_fd(PyObject
*self
, PyObject
*args
)
281 if (!PyArg_ParseTuple(args
, "i:set_wakeup_fd", &fd
))
284 if (PyThread_get_thread_ident() != main_thread
) {
285 PyErr_SetString(PyExc_ValueError
,
286 "set_wakeup_fd only works in main thread");
290 if (fd
!= -1 && fstat(fd
, &buf
) != 0) {
291 PyErr_SetString(PyExc_ValueError
, "invalid fd");
296 return PyLong_FromLong(old_fd
);
299 PyDoc_STRVAR(set_wakeup_fd_doc
,
300 "set_wakeup_fd(fd) -> fd\n\
302 Sets the fd to be written to (with '\\0') when a signal\n\
303 comes in. A library can use this to wakeup select or poll.\n\
304 The previous fd is returned.\n\
306 The fd must be non-blocking.");
308 /* C API for the same, without all the error checking */
310 PySignal_SetWakeupFd(int fd
)
312 int old_fd
= wakeup_fd
;
320 /* List of functions defined in the module */
321 static PyMethodDef signal_methods
[] = {
323 {"alarm", signal_alarm
, METH_VARARGS
, alarm_doc
},
325 {"signal", signal_signal
, METH_VARARGS
, signal_doc
},
326 {"getsignal", signal_getsignal
, METH_VARARGS
, getsignal_doc
},
327 {"set_wakeup_fd", signal_set_wakeup_fd
, METH_VARARGS
, set_wakeup_fd_doc
},
329 {"pause", (PyCFunction
)signal_pause
,
330 METH_NOARGS
,pause_doc
},
332 {"default_int_handler", signal_default_int_handler
,
333 METH_VARARGS
, default_int_handler_doc
},
334 {NULL
, NULL
} /* sentinel */
338 PyDoc_STRVAR(module_doc
,
339 "This module provides mechanisms to use signal handlers in Python.\n\
343 alarm() -- cause SIGALRM after a specified time [Unix only]\n\
344 signal() -- set the action for a given signal\n\
345 getsignal() -- get the signal action for a given signal\n\
346 pause() -- wait until a signal arrives [Unix only]\n\
347 default_int_handler() -- default SIGINT handler\n\
351 SIG_DFL -- used to refer to the system default handler\n\
352 SIG_IGN -- used to ignore the signal\n\
353 NSIG -- number of defined signals\n\
355 SIGINT, SIGTERM, etc. -- signal numbers\n\
357 *** IMPORTANT NOTICE ***\n\
358 A signal handler function is called with two arguments:\n\
359 the first is the signal number, the second is the interrupted stack frame.");
368 main_thread
= PyThread_get_thread_ident();
372 /* Create the module and add the functions */
373 m
= Py_InitModule3("signal", signal_methods
, module_doc
);
377 /* Add some symbolic constants to the module */
378 d
= PyModule_GetDict(m
);
380 x
= DefaultHandler
= PyLong_FromVoidPtr((void *)SIG_DFL
);
381 if (!x
|| PyDict_SetItemString(d
, "SIG_DFL", x
) < 0)
384 x
= IgnoreHandler
= PyLong_FromVoidPtr((void *)SIG_IGN
);
385 if (!x
|| PyDict_SetItemString(d
, "SIG_IGN", x
) < 0)
388 x
= PyInt_FromLong((long)NSIG
);
389 if (!x
|| PyDict_SetItemString(d
, "NSIG", x
) < 0)
393 x
= IntHandler
= PyDict_GetItemString(d
, "default_int_handler");
396 Py_INCREF(IntHandler
);
398 Handlers
[0].tripped
= 0;
399 for (i
= 1; i
< NSIG
; i
++) {
402 Handlers
[i
].tripped
= 0;
404 Handlers
[i
].func
= DefaultHandler
;
405 else if (t
== SIG_IGN
)
406 Handlers
[i
].func
= IgnoreHandler
;
408 Handlers
[i
].func
= Py_None
; /* None of our business */
409 Py_INCREF(Handlers
[i
].func
);
411 if (Handlers
[SIGINT
].func
== DefaultHandler
) {
412 /* Install default int handler */
413 Py_INCREF(IntHandler
);
414 Py_DECREF(Handlers
[SIGINT
].func
);
415 Handlers
[SIGINT
].func
= IntHandler
;
416 old_siginthandler
= PyOS_setsig(SIGINT
, signal_handler
);
420 x
= PyInt_FromLong(SIGHUP
);
421 PyDict_SetItemString(d
, "SIGHUP", x
);
425 x
= PyInt_FromLong(SIGINT
);
426 PyDict_SetItemString(d
, "SIGINT", x
);
430 x
= PyInt_FromLong(SIGBREAK
);
431 PyDict_SetItemString(d
, "SIGBREAK", x
);
435 x
= PyInt_FromLong(SIGQUIT
);
436 PyDict_SetItemString(d
, "SIGQUIT", x
);
440 x
= PyInt_FromLong(SIGILL
);
441 PyDict_SetItemString(d
, "SIGILL", x
);
445 x
= PyInt_FromLong(SIGTRAP
);
446 PyDict_SetItemString(d
, "SIGTRAP", x
);
450 x
= PyInt_FromLong(SIGIOT
);
451 PyDict_SetItemString(d
, "SIGIOT", x
);
455 x
= PyInt_FromLong(SIGABRT
);
456 PyDict_SetItemString(d
, "SIGABRT", x
);
460 x
= PyInt_FromLong(SIGEMT
);
461 PyDict_SetItemString(d
, "SIGEMT", x
);
465 x
= PyInt_FromLong(SIGFPE
);
466 PyDict_SetItemString(d
, "SIGFPE", x
);
470 x
= PyInt_FromLong(SIGKILL
);
471 PyDict_SetItemString(d
, "SIGKILL", x
);
475 x
= PyInt_FromLong(SIGBUS
);
476 PyDict_SetItemString(d
, "SIGBUS", x
);
480 x
= PyInt_FromLong(SIGSEGV
);
481 PyDict_SetItemString(d
, "SIGSEGV", x
);
485 x
= PyInt_FromLong(SIGSYS
);
486 PyDict_SetItemString(d
, "SIGSYS", x
);
490 x
= PyInt_FromLong(SIGPIPE
);
491 PyDict_SetItemString(d
, "SIGPIPE", x
);
495 x
= PyInt_FromLong(SIGALRM
);
496 PyDict_SetItemString(d
, "SIGALRM", x
);
500 x
= PyInt_FromLong(SIGTERM
);
501 PyDict_SetItemString(d
, "SIGTERM", x
);
505 x
= PyInt_FromLong(SIGUSR1
);
506 PyDict_SetItemString(d
, "SIGUSR1", x
);
510 x
= PyInt_FromLong(SIGUSR2
);
511 PyDict_SetItemString(d
, "SIGUSR2", x
);
515 x
= PyInt_FromLong(SIGCLD
);
516 PyDict_SetItemString(d
, "SIGCLD", x
);
520 x
= PyInt_FromLong(SIGCHLD
);
521 PyDict_SetItemString(d
, "SIGCHLD", x
);
525 x
= PyInt_FromLong(SIGPWR
);
526 PyDict_SetItemString(d
, "SIGPWR", x
);
530 x
= PyInt_FromLong(SIGIO
);
531 PyDict_SetItemString(d
, "SIGIO", x
);
535 x
= PyInt_FromLong(SIGURG
);
536 PyDict_SetItemString(d
, "SIGURG", x
);
540 x
= PyInt_FromLong(SIGWINCH
);
541 PyDict_SetItemString(d
, "SIGWINCH", x
);
545 x
= PyInt_FromLong(SIGPOLL
);
546 PyDict_SetItemString(d
, "SIGPOLL", x
);
550 x
= PyInt_FromLong(SIGSTOP
);
551 PyDict_SetItemString(d
, "SIGSTOP", x
);
555 x
= PyInt_FromLong(SIGTSTP
);
556 PyDict_SetItemString(d
, "SIGTSTP", x
);
560 x
= PyInt_FromLong(SIGCONT
);
561 PyDict_SetItemString(d
, "SIGCONT", x
);
565 x
= PyInt_FromLong(SIGTTIN
);
566 PyDict_SetItemString(d
, "SIGTTIN", x
);
570 x
= PyInt_FromLong(SIGTTOU
);
571 PyDict_SetItemString(d
, "SIGTTOU", x
);
575 x
= PyInt_FromLong(SIGVTALRM
);
576 PyDict_SetItemString(d
, "SIGVTALRM", x
);
580 x
= PyInt_FromLong(SIGPROF
);
581 PyDict_SetItemString(d
, "SIGPROF", x
);
585 x
= PyInt_FromLong(SIGXCPU
);
586 PyDict_SetItemString(d
, "SIGXCPU", x
);
590 x
= PyInt_FromLong(SIGXFSZ
);
591 PyDict_SetItemString(d
, "SIGXFSZ", x
);
595 x
= PyInt_FromLong(SIGRTMIN
);
596 PyDict_SetItemString(d
, "SIGRTMIN", x
);
600 x
= PyInt_FromLong(SIGRTMAX
);
601 PyDict_SetItemString(d
, "SIGRTMAX", x
);
605 x
= PyInt_FromLong(SIGINFO
);
606 PyDict_SetItemString(d
, "SIGINFO", x
);
609 if (!PyErr_Occurred())
612 /* Check for errors */
623 PyOS_setsig(SIGINT
, old_siginthandler
);
624 old_siginthandler
= SIG_DFL
;
626 for (i
= 1; i
< NSIG
; i
++) {
627 func
= Handlers
[i
].func
;
628 Handlers
[i
].tripped
= 0;
629 Handlers
[i
].func
= NULL
;
630 if (i
!= SIGINT
&& func
!= NULL
&& func
!= Py_None
&&
631 func
!= DefaultHandler
&& func
!= IgnoreHandler
)
632 PyOS_setsig(i
, SIG_DFL
);
636 Py_XDECREF(IntHandler
);
638 Py_XDECREF(DefaultHandler
);
639 DefaultHandler
= NULL
;
640 Py_XDECREF(IgnoreHandler
);
641 IgnoreHandler
= NULL
;
645 /* Declared in pyerrors.h */
647 PyErr_CheckSignals(void)
656 if (PyThread_get_thread_ident() != main_thread
)
661 * The is_stripped variable is meant to speed up the calls to
662 * PyErr_CheckSignals (both directly or via pending calls) when no
663 * signal has arrived. This variable is set to 1 when a signal arrives
664 * and it is set to 0 here, when we know some signals arrived. This way
665 * we can run the registered handlers with no signals blocked.
667 * NOTE: with this approach we can have a situation where is_tripped is
668 * 1 but we have no more signals to handle (Handlers[i].tripped
669 * is 0 for every signal i). This won't do us any harm (except
670 * we're gonna spent some cycles for nothing). This happens when
671 * we receive a signal i after we zero is_tripped and before we
672 * check Handlers[i].tripped.
676 if (!(f
= (PyObject
*)PyEval_GetFrame()))
679 for (i
= 1; i
< NSIG
; i
++) {
680 if (Handlers
[i
].tripped
) {
681 PyObject
*result
= NULL
;
682 PyObject
*arglist
= Py_BuildValue("(iO)", i
, f
);
683 Handlers
[i
].tripped
= 0;
686 result
= PyEval_CallObject(Handlers
[i
].func
,
701 /* Replacements for intrcheck.c functionality
702 * Declared in pyerrors.h
705 PyErr_SetInterrupt(void)
708 Handlers
[SIGINT
].tripped
= 1;
709 Py_AddPendingCall((int (*)(void *))PyErr_CheckSignals
, NULL
);
713 PyOS_InitInterrupts(void)
716 _PyImport_FixupExtension("signal", "signal");
720 PyOS_FiniInterrupts(void)
726 PyOS_InterruptOccurred(void)
728 if (Handlers
[SIGINT
].tripped
) {
730 if (PyThread_get_thread_ident() != main_thread
)
733 Handlers
[SIGINT
].tripped
= 0;
743 PyEval_ReInitThreads();
744 main_thread
= PyThread_get_thread_ident();
746 _PyImport_ReInitLock();