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
);
323 /* Add some symbolic constants to the module */
324 d
= PyModule_GetDict(m
);
326 x
= DefaultHandler
= PyLong_FromVoidPtr((void *)SIG_DFL
);
327 if (!x
|| PyDict_SetItemString(d
, "SIG_DFL", x
) < 0)
330 x
= IgnoreHandler
= PyLong_FromVoidPtr((void *)SIG_IGN
);
331 if (!x
|| PyDict_SetItemString(d
, "SIG_IGN", x
) < 0)
334 x
= PyInt_FromLong((long)NSIG
);
335 if (!x
|| PyDict_SetItemString(d
, "NSIG", x
) < 0)
339 x
= IntHandler
= PyDict_GetItemString(d
, "default_int_handler");
342 Py_INCREF(IntHandler
);
344 Handlers
[0].tripped
= 0;
345 for (i
= 1; i
< NSIG
; i
++) {
348 Handlers
[i
].tripped
= 0;
350 Handlers
[i
].func
= DefaultHandler
;
351 else if (t
== SIG_IGN
)
352 Handlers
[i
].func
= IgnoreHandler
;
354 Handlers
[i
].func
= Py_None
; /* None of our business */
355 Py_INCREF(Handlers
[i
].func
);
357 if (Handlers
[SIGINT
].func
== DefaultHandler
) {
358 /* Install default int handler */
359 Py_INCREF(IntHandler
);
360 Py_DECREF(Handlers
[SIGINT
].func
);
361 Handlers
[SIGINT
].func
= IntHandler
;
362 old_siginthandler
= PyOS_setsig(SIGINT
, signal_handler
);
366 x
= PyInt_FromLong(SIGHUP
);
367 PyDict_SetItemString(d
, "SIGHUP", x
);
371 x
= PyInt_FromLong(SIGINT
);
372 PyDict_SetItemString(d
, "SIGINT", x
);
376 x
= PyInt_FromLong(SIGBREAK
);
377 PyDict_SetItemString(d
, "SIGBREAK", x
);
381 x
= PyInt_FromLong(SIGQUIT
);
382 PyDict_SetItemString(d
, "SIGQUIT", x
);
386 x
= PyInt_FromLong(SIGILL
);
387 PyDict_SetItemString(d
, "SIGILL", x
);
391 x
= PyInt_FromLong(SIGTRAP
);
392 PyDict_SetItemString(d
, "SIGTRAP", x
);
396 x
= PyInt_FromLong(SIGIOT
);
397 PyDict_SetItemString(d
, "SIGIOT", x
);
401 x
= PyInt_FromLong(SIGABRT
);
402 PyDict_SetItemString(d
, "SIGABRT", x
);
406 x
= PyInt_FromLong(SIGEMT
);
407 PyDict_SetItemString(d
, "SIGEMT", x
);
411 x
= PyInt_FromLong(SIGFPE
);
412 PyDict_SetItemString(d
, "SIGFPE", x
);
416 x
= PyInt_FromLong(SIGKILL
);
417 PyDict_SetItemString(d
, "SIGKILL", x
);
421 x
= PyInt_FromLong(SIGBUS
);
422 PyDict_SetItemString(d
, "SIGBUS", x
);
426 x
= PyInt_FromLong(SIGSEGV
);
427 PyDict_SetItemString(d
, "SIGSEGV", x
);
431 x
= PyInt_FromLong(SIGSYS
);
432 PyDict_SetItemString(d
, "SIGSYS", x
);
436 x
= PyInt_FromLong(SIGPIPE
);
437 PyDict_SetItemString(d
, "SIGPIPE", x
);
441 x
= PyInt_FromLong(SIGALRM
);
442 PyDict_SetItemString(d
, "SIGALRM", x
);
446 x
= PyInt_FromLong(SIGTERM
);
447 PyDict_SetItemString(d
, "SIGTERM", x
);
451 x
= PyInt_FromLong(SIGUSR1
);
452 PyDict_SetItemString(d
, "SIGUSR1", x
);
456 x
= PyInt_FromLong(SIGUSR2
);
457 PyDict_SetItemString(d
, "SIGUSR2", x
);
461 x
= PyInt_FromLong(SIGCLD
);
462 PyDict_SetItemString(d
, "SIGCLD", x
);
466 x
= PyInt_FromLong(SIGCHLD
);
467 PyDict_SetItemString(d
, "SIGCHLD", x
);
471 x
= PyInt_FromLong(SIGPWR
);
472 PyDict_SetItemString(d
, "SIGPWR", x
);
476 x
= PyInt_FromLong(SIGIO
);
477 PyDict_SetItemString(d
, "SIGIO", x
);
481 x
= PyInt_FromLong(SIGURG
);
482 PyDict_SetItemString(d
, "SIGURG", x
);
486 x
= PyInt_FromLong(SIGWINCH
);
487 PyDict_SetItemString(d
, "SIGWINCH", x
);
491 x
= PyInt_FromLong(SIGPOLL
);
492 PyDict_SetItemString(d
, "SIGPOLL", x
);
496 x
= PyInt_FromLong(SIGSTOP
);
497 PyDict_SetItemString(d
, "SIGSTOP", x
);
501 x
= PyInt_FromLong(SIGTSTP
);
502 PyDict_SetItemString(d
, "SIGTSTP", x
);
506 x
= PyInt_FromLong(SIGCONT
);
507 PyDict_SetItemString(d
, "SIGCONT", x
);
511 x
= PyInt_FromLong(SIGTTIN
);
512 PyDict_SetItemString(d
, "SIGTTIN", x
);
516 x
= PyInt_FromLong(SIGTTOU
);
517 PyDict_SetItemString(d
, "SIGTTOU", x
);
521 x
= PyInt_FromLong(SIGVTALRM
);
522 PyDict_SetItemString(d
, "SIGVTALRM", x
);
526 x
= PyInt_FromLong(SIGPROF
);
527 PyDict_SetItemString(d
, "SIGPROF", x
);
531 x
= PyInt_FromLong(SIGXCPU
);
532 PyDict_SetItemString(d
, "SIGXCPU", x
);
536 x
= PyInt_FromLong(SIGXFSZ
);
537 PyDict_SetItemString(d
, "SIGXFSZ", x
);
541 x
= PyInt_FromLong(SIGRTMIN
);
542 PyDict_SetItemString(d
, "SIGRTMIN", x
);
546 x
= PyInt_FromLong(SIGRTMAX
);
547 PyDict_SetItemString(d
, "SIGRTMAX", x
);
551 x
= PyInt_FromLong(SIGINFO
);
552 PyDict_SetItemString(d
, "SIGINFO", x
);
555 if (!PyErr_Occurred())
558 /* Check for errors */
569 PyOS_setsig(SIGINT
, old_siginthandler
);
570 old_siginthandler
= SIG_DFL
;
572 for (i
= 1; i
< NSIG
; i
++) {
573 func
= Handlers
[i
].func
;
574 Handlers
[i
].tripped
= 0;
575 Handlers
[i
].func
= NULL
;
576 if (i
!= SIGINT
&& func
!= NULL
&& func
!= Py_None
&&
577 func
!= DefaultHandler
&& func
!= IgnoreHandler
)
578 PyOS_setsig(i
, SIG_DFL
);
582 Py_XDECREF(IntHandler
);
584 Py_XDECREF(DefaultHandler
);
585 DefaultHandler
= NULL
;
586 Py_XDECREF(IgnoreHandler
);
587 IgnoreHandler
= NULL
;
591 /* Declared in pyerrors.h */
593 PyErr_CheckSignals(void)
601 if (PyThread_get_thread_ident() != main_thread
)
604 if (!(f
= (PyObject
*)PyEval_GetFrame()))
607 for (i
= 1; i
< NSIG
; i
++) {
608 if (Handlers
[i
].tripped
) {
609 PyObject
*result
= NULL
;
610 PyObject
*arglist
= Py_BuildValue("(iO)", i
, f
);
611 Handlers
[i
].tripped
= 0;
614 result
= PyEval_CallObject(Handlers
[i
].func
,
629 /* Replacements for intrcheck.c functionality
630 * Declared in pyerrors.h
633 PyErr_SetInterrupt(void)
636 Handlers
[SIGINT
].tripped
= 1;
637 Py_AddPendingCall((int (*)(void *))PyErr_CheckSignals
, NULL
);
641 PyOS_InitInterrupts(void)
644 _PyImport_FixupExtension("signal", "signal");
648 PyOS_FiniInterrupts(void)
654 PyOS_InterruptOccurred(void)
656 if (Handlers
[SIGINT
].tripped
) {
658 if (PyThread_get_thread_ident() != main_thread
)
661 Handlers
[SIGINT
].tripped
= 0;
671 PyEval_ReInitThreads();
672 main_thread
= PyThread_get_thread_ident();
674 _PyImport_ReInitLock();