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 installed 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 PyOS_setsig(sig_num
, signal_handler
);
146 signal_alarm(PyObject
*self
, PyObject
*args
)
149 if (!PyArg_ParseTuple(args
, "i:alarm", &t
))
151 /* alarm() returns the number of seconds remaining */
152 return PyInt_FromLong((long)alarm(t
));
155 PyDoc_STRVAR(alarm_doc
,
158 Arrange for SIGALRM to arrive after the given number of seconds.");
163 signal_pause(PyObject
*self
)
165 Py_BEGIN_ALLOW_THREADS
168 /* make sure that any exceptions that got raised are propagated
171 if (PyErr_CheckSignals())
177 PyDoc_STRVAR(pause_doc
,
180 Wait until a signal arrives.");
186 signal_signal(PyObject
*self
, PyObject
*args
)
190 PyObject
*old_handler
;
192 if (!PyArg_ParseTuple(args
, "iO:signal", &sig_num
, &obj
))
195 if (PyThread_get_thread_ident() != main_thread
) {
196 PyErr_SetString(PyExc_ValueError
,
197 "signal only works in main thread");
201 if (sig_num
< 1 || sig_num
>= NSIG
) {
202 PyErr_SetString(PyExc_ValueError
,
203 "signal number out of range");
206 if (obj
== IgnoreHandler
)
208 else if (obj
== DefaultHandler
)
210 else if (!PyCallable_Check(obj
)) {
211 PyErr_SetString(PyExc_TypeError
,
212 "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
216 func
= signal_handler
;
217 if (PyOS_setsig(sig_num
, func
) == SIG_ERR
) {
218 PyErr_SetFromErrno(PyExc_RuntimeError
);
221 old_handler
= Handlers
[sig_num
].func
;
222 Handlers
[sig_num
].tripped
= 0;
224 Handlers
[sig_num
].func
= obj
;
228 PyDoc_STRVAR(signal_doc
,
229 "signal(sig, action) -> action\n\
231 Set the action for the given signal. The action can be SIG_DFL,\n\
232 SIG_IGN, or a callable Python object. The previous action is\n\
233 returned. See getsignal() for possible return values.\n\
235 *** IMPORTANT NOTICE ***\n\
236 A signal handler function is called with two arguments:\n\
237 the first is the signal number, the second is the interrupted stack frame.");
241 signal_getsignal(PyObject
*self
, PyObject
*args
)
244 PyObject
*old_handler
;
245 if (!PyArg_ParseTuple(args
, "i:getsignal", &sig_num
))
247 if (sig_num
< 1 || sig_num
>= NSIG
) {
248 PyErr_SetString(PyExc_ValueError
,
249 "signal number out of range");
252 old_handler
= Handlers
[sig_num
].func
;
253 Py_INCREF(old_handler
);
257 PyDoc_STRVAR(getsignal_doc
,
258 "getsignal(sig) -> action\n\
260 Return the current action for the given signal. The return value can be:\n\
261 SIG_IGN -- if the signal is being ignored\n\
262 SIG_DFL -- if the default action for the signal is in effect\n\
263 None -- if an unknown handler is in effect\n\
264 anything else -- the callable Python object used as a handler");
267 /* List of functions defined in the module */
268 static PyMethodDef signal_methods
[] = {
270 {"alarm", signal_alarm
, METH_VARARGS
, alarm_doc
},
272 {"signal", signal_signal
, METH_VARARGS
, signal_doc
},
273 {"getsignal", signal_getsignal
, METH_VARARGS
, getsignal_doc
},
275 {"pause", (PyCFunction
)signal_pause
,
276 METH_NOARGS
,pause_doc
},
278 {"default_int_handler", signal_default_int_handler
,
279 METH_VARARGS
, default_int_handler_doc
},
280 {NULL
, NULL
} /* sentinel */
284 PyDoc_STRVAR(module_doc
,
285 "This module provides mechanisms to use signal handlers in Python.\n\
289 alarm() -- cause SIGALRM after a specified time [Unix only]\n\
290 signal() -- set the action for a given signal\n\
291 getsignal() -- get the signal action for a given signal\n\
292 pause() -- wait until a signal arrives [Unix only]\n\
293 default_int_handler() -- default SIGINT handler\n\
297 SIG_DFL -- used to refer to the system default handler\n\
298 SIG_IGN -- used to ignore the signal\n\
299 NSIG -- number of defined signals\n\
301 SIGINT, SIGTERM, etc. -- signal numbers\n\
303 *** IMPORTANT NOTICE ***\n\
304 A signal handler function is called with two arguments:\n\
305 the first is the signal number, the second is the interrupted stack frame.");
314 main_thread
= PyThread_get_thread_ident();
318 /* Create the module and add the functions */
319 m
= Py_InitModule3("signal", signal_methods
, module_doc
);
321 /* Add some symbolic constants to the module */
322 d
= PyModule_GetDict(m
);
324 x
= DefaultHandler
= PyLong_FromVoidPtr((void *)SIG_DFL
);
325 if (!x
|| PyDict_SetItemString(d
, "SIG_DFL", x
) < 0)
328 x
= IgnoreHandler
= PyLong_FromVoidPtr((void *)SIG_IGN
);
329 if (!x
|| PyDict_SetItemString(d
, "SIG_IGN", x
) < 0)
332 x
= PyInt_FromLong((long)NSIG
);
333 if (!x
|| PyDict_SetItemString(d
, "NSIG", x
) < 0)
337 x
= IntHandler
= PyDict_GetItemString(d
, "default_int_handler");
340 Py_INCREF(IntHandler
);
342 Handlers
[0].tripped
= 0;
343 for (i
= 1; i
< NSIG
; i
++) {
346 Handlers
[i
].tripped
= 0;
348 Handlers
[i
].func
= DefaultHandler
;
349 else if (t
== SIG_IGN
)
350 Handlers
[i
].func
= IgnoreHandler
;
352 Handlers
[i
].func
= Py_None
; /* None of our business */
353 Py_INCREF(Handlers
[i
].func
);
355 if (Handlers
[SIGINT
].func
== DefaultHandler
) {
356 /* Install default int handler */
357 Py_INCREF(IntHandler
);
358 Py_DECREF(Handlers
[SIGINT
].func
);
359 Handlers
[SIGINT
].func
= IntHandler
;
360 old_siginthandler
= PyOS_setsig(SIGINT
, signal_handler
);
364 x
= PyInt_FromLong(SIGHUP
);
365 PyDict_SetItemString(d
, "SIGHUP", x
);
369 x
= PyInt_FromLong(SIGINT
);
370 PyDict_SetItemString(d
, "SIGINT", x
);
374 x
= PyInt_FromLong(SIGBREAK
);
375 PyDict_SetItemString(d
, "SIGBREAK", x
);
379 x
= PyInt_FromLong(SIGQUIT
);
380 PyDict_SetItemString(d
, "SIGQUIT", x
);
384 x
= PyInt_FromLong(SIGILL
);
385 PyDict_SetItemString(d
, "SIGILL", x
);
389 x
= PyInt_FromLong(SIGTRAP
);
390 PyDict_SetItemString(d
, "SIGTRAP", x
);
394 x
= PyInt_FromLong(SIGIOT
);
395 PyDict_SetItemString(d
, "SIGIOT", x
);
399 x
= PyInt_FromLong(SIGABRT
);
400 PyDict_SetItemString(d
, "SIGABRT", x
);
404 x
= PyInt_FromLong(SIGEMT
);
405 PyDict_SetItemString(d
, "SIGEMT", x
);
409 x
= PyInt_FromLong(SIGFPE
);
410 PyDict_SetItemString(d
, "SIGFPE", x
);
414 x
= PyInt_FromLong(SIGKILL
);
415 PyDict_SetItemString(d
, "SIGKILL", x
);
419 x
= PyInt_FromLong(SIGBUS
);
420 PyDict_SetItemString(d
, "SIGBUS", x
);
424 x
= PyInt_FromLong(SIGSEGV
);
425 PyDict_SetItemString(d
, "SIGSEGV", x
);
429 x
= PyInt_FromLong(SIGSYS
);
430 PyDict_SetItemString(d
, "SIGSYS", x
);
434 x
= PyInt_FromLong(SIGPIPE
);
435 PyDict_SetItemString(d
, "SIGPIPE", x
);
439 x
= PyInt_FromLong(SIGALRM
);
440 PyDict_SetItemString(d
, "SIGALRM", x
);
444 x
= PyInt_FromLong(SIGTERM
);
445 PyDict_SetItemString(d
, "SIGTERM", x
);
449 x
= PyInt_FromLong(SIGUSR1
);
450 PyDict_SetItemString(d
, "SIGUSR1", x
);
454 x
= PyInt_FromLong(SIGUSR2
);
455 PyDict_SetItemString(d
, "SIGUSR2", x
);
459 x
= PyInt_FromLong(SIGCLD
);
460 PyDict_SetItemString(d
, "SIGCLD", x
);
464 x
= PyInt_FromLong(SIGCHLD
);
465 PyDict_SetItemString(d
, "SIGCHLD", x
);
469 x
= PyInt_FromLong(SIGPWR
);
470 PyDict_SetItemString(d
, "SIGPWR", x
);
474 x
= PyInt_FromLong(SIGIO
);
475 PyDict_SetItemString(d
, "SIGIO", x
);
479 x
= PyInt_FromLong(SIGURG
);
480 PyDict_SetItemString(d
, "SIGURG", x
);
484 x
= PyInt_FromLong(SIGWINCH
);
485 PyDict_SetItemString(d
, "SIGWINCH", x
);
489 x
= PyInt_FromLong(SIGPOLL
);
490 PyDict_SetItemString(d
, "SIGPOLL", x
);
494 x
= PyInt_FromLong(SIGSTOP
);
495 PyDict_SetItemString(d
, "SIGSTOP", x
);
499 x
= PyInt_FromLong(SIGTSTP
);
500 PyDict_SetItemString(d
, "SIGTSTP", x
);
504 x
= PyInt_FromLong(SIGCONT
);
505 PyDict_SetItemString(d
, "SIGCONT", x
);
509 x
= PyInt_FromLong(SIGTTIN
);
510 PyDict_SetItemString(d
, "SIGTTIN", x
);
514 x
= PyInt_FromLong(SIGTTOU
);
515 PyDict_SetItemString(d
, "SIGTTOU", x
);
519 x
= PyInt_FromLong(SIGVTALRM
);
520 PyDict_SetItemString(d
, "SIGVTALRM", x
);
524 x
= PyInt_FromLong(SIGPROF
);
525 PyDict_SetItemString(d
, "SIGPROF", x
);
529 x
= PyInt_FromLong(SIGXCPU
);
530 PyDict_SetItemString(d
, "SIGXCPU", x
);
534 x
= PyInt_FromLong(SIGXFSZ
);
535 PyDict_SetItemString(d
, "SIGXFSZ", x
);
539 x
= PyInt_FromLong(SIGRTMIN
);
540 PyDict_SetItemString(d
, "SIGRTMIN", x
);
544 x
= PyInt_FromLong(SIGRTMAX
);
545 PyDict_SetItemString(d
, "SIGRTMAX", x
);
549 x
= PyInt_FromLong(SIGINFO
);
550 PyDict_SetItemString(d
, "SIGINFO", x
);
553 if (!PyErr_Occurred())
556 /* Check for errors */
567 PyOS_setsig(SIGINT
, old_siginthandler
);
568 old_siginthandler
= SIG_DFL
;
570 for (i
= 1; i
< NSIG
; i
++) {
571 func
= Handlers
[i
].func
;
572 Handlers
[i
].tripped
= 0;
573 Handlers
[i
].func
= NULL
;
574 if (i
!= SIGINT
&& func
!= NULL
&& func
!= Py_None
&&
575 func
!= DefaultHandler
&& func
!= IgnoreHandler
)
576 PyOS_setsig(i
, SIG_DFL
);
580 Py_XDECREF(IntHandler
);
582 Py_XDECREF(DefaultHandler
);
583 DefaultHandler
= NULL
;
584 Py_XDECREF(IgnoreHandler
);
585 IgnoreHandler
= NULL
;
589 /* Declared in pyerrors.h */
591 PyErr_CheckSignals(void)
599 if (PyThread_get_thread_ident() != main_thread
)
602 if (!(f
= (PyObject
*)PyEval_GetFrame()))
605 for (i
= 1; i
< NSIG
; i
++) {
606 if (Handlers
[i
].tripped
) {
607 PyObject
*result
= NULL
;
608 PyObject
*arglist
= Py_BuildValue("(iO)", i
, f
);
609 Handlers
[i
].tripped
= 0;
612 result
= PyEval_CallObject(Handlers
[i
].func
,
627 /* Replacements for intrcheck.c functionality
628 * Declared in pyerrors.h
631 PyErr_SetInterrupt(void)
634 Handlers
[SIGINT
].tripped
= 1;
635 Py_AddPendingCall((int (*)(void *))PyErr_CheckSignals
, NULL
);
639 PyOS_InitInterrupts(void)
642 _PyImport_FixupExtension("signal", "signal");
646 PyOS_FiniInterrupts(void)
652 PyOS_InterruptOccurred(void)
654 if (Handlers
[SIGINT
].tripped
) {
656 if (PyThread_get_thread_ident() != main_thread
)
659 Handlers
[SIGINT
].tripped
= 0;
669 PyEval_ReInitThreads();
670 main_thread
= PyThread_get_thread_ident();
672 _PyImport_ReInitLock();