2 /* Signal module -- many thanks to Lance Ellinghaus */
4 /* XXX Signals should be recorded per thread, now we have thread state. */
20 #define SIG_ERR ((PyOS_sighandler_t)(-1))
30 # define NSIG _NSIG /* For BSD/SysV */
31 # elif defined(_SIGMAX)
32 # define NSIG (_SIGMAX + 1) /* For QNX */
33 # elif defined(SIGMAX)
34 # define NSIG (SIGMAX + 1) /* For djgpp */
36 # define NSIG 64 /* Use a reasonable default value */
42 NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS
44 When threads are supported, we want the following semantics:
46 - only the main thread can set a signal handler
47 - any thread can get a signal handler
48 - signals are only delivered to the main thread
50 I.e. we don't support "synchronous signals" like SIGFPE (catching
51 this doesn't make much sense in Python anyway) nor do we support
52 signals as a means of inter-thread communication, since not all
53 thread implementations support that (at least our thread library
56 We still have the problem that in some implementations signals
57 generated by the keyboard (e.g. SIGINT) are delivered to all
58 threads (e.g. SGI), while in others (e.g. Solaris) such signals are
59 delivered to one random thread (an intermediate possibility would
60 be to deliver it to the main thread -- POSIX?). For now, we have
61 a working implementation that works in all three cases -- the
62 handler ignores signals if getpid() isn't the same as in the main
63 thread. XXX This is a hack.
65 GNU pth is a user-space threading library, and as such, all threads
66 run within the same process. In this case, if the currently running
67 thread is not the main_thread, send the signal to the main_thread.
71 #include <sys/types.h> /* For pid_t */
73 static long main_thread
;
74 static pid_t main_pid
;
82 static int is_tripped
= 0; /* Speed up sigcheck() when none tripped */
84 static PyObject
*DefaultHandler
;
85 static PyObject
*IgnoreHandler
;
86 static PyObject
*IntHandler
;
88 /* On Solaris 8, gcc will produce a warning that the function
89 declaration is not a prototype. This is caused by the definition of
90 SIG_DFL as (void (*)())0; the correct declaration would have been
93 static PyOS_sighandler_t old_siginthandler
= SIG_DFL
;
97 signal_default_int_handler(PyObject
*self
, PyObject
*args
)
99 PyErr_SetNone(PyExc_KeyboardInterrupt
);
103 static char default_int_handler_doc
[] =
104 "default_int_handler(...)\n\
106 The default handler for SIGINT instated by Python.\n\
107 It raises KeyboardInterrupt.";
111 checksignals_witharg(void * unused
)
113 return PyErr_CheckSignals();
117 signal_handler(int sig_num
)
121 if (PyThread_get_thread_ident() != main_thread
) {
122 pth_raise(*(pth_t
*) main_thread
, sig_num
);
126 /* See NOTES section above */
127 if (getpid() == main_pid
) {
130 Handlers
[sig_num
].tripped
= 1;
131 Py_AddPendingCall(checksignals_witharg
, NULL
);
136 if (sig_num
== SIGCHLD
) {
137 /* To avoid infinite recursion, this signal remains
138 reset until explicit re-instated.
139 Don't clear the 'func' field as it is our pointer
140 to the Python handler... */
144 #ifdef HAVE_SIGINTERRUPT
145 siginterrupt(sig_num
, 1);
147 PyOS_setsig(sig_num
, signal_handler
);
153 signal_alarm(PyObject
*self
, PyObject
*args
)
156 if (!PyArg_Parse(args
, "i", &t
))
158 /* alarm() returns the number of seconds remaining */
159 return PyInt_FromLong((long)alarm(t
));
162 static char alarm_doc
[] =
165 Arrange for SIGALRM to arrive after the given number of seconds.";
170 signal_pause(PyObject
*self
, PyObject
*args
)
172 if (!PyArg_NoArgs(args
))
175 Py_BEGIN_ALLOW_THREADS
178 /* make sure that any exceptions that got raised are propagated
181 if (PyErr_CheckSignals())
187 static char pause_doc
[] =
190 Wait until a signal arrives.";
196 signal_signal(PyObject
*self
, PyObject
*args
)
200 PyObject
*old_handler
;
202 if (!PyArg_Parse(args
, "(iO)", &sig_num
, &obj
))
205 if (PyThread_get_thread_ident() != main_thread
) {
206 PyErr_SetString(PyExc_ValueError
,
207 "signal only works in main thread");
211 if (sig_num
< 1 || sig_num
>= NSIG
) {
212 PyErr_SetString(PyExc_ValueError
,
213 "signal number out of range");
216 if (obj
== IgnoreHandler
)
218 else if (obj
== DefaultHandler
)
220 else if (!PyCallable_Check(obj
)) {
221 PyErr_SetString(PyExc_TypeError
,
222 "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
226 func
= signal_handler
;
227 #ifdef HAVE_SIGINTERRUPT
228 siginterrupt(sig_num
, 1);
230 if (PyOS_setsig(sig_num
, func
) == SIG_ERR
) {
231 PyErr_SetFromErrno(PyExc_RuntimeError
);
234 old_handler
= Handlers
[sig_num
].func
;
235 Handlers
[sig_num
].tripped
= 0;
237 Handlers
[sig_num
].func
= obj
;
241 static char signal_doc
[] =
242 "signal(sig, action) -> action\n\
244 Set the action for the given signal. The action can be SIG_DFL,\n\
245 SIG_IGN, or a callable Python object. The previous action is\n\
246 returned. See getsignal() for possible return values.\n\
248 *** IMPORTANT NOTICE ***\n\
249 A signal handler function is called with two arguments:\n\
250 the first is the signal number, the second is the interrupted stack frame.";
254 signal_getsignal(PyObject
*self
, PyObject
*args
)
257 PyObject
*old_handler
;
258 if (!PyArg_Parse(args
, "i", &sig_num
))
260 if (sig_num
< 1 || sig_num
>= NSIG
) {
261 PyErr_SetString(PyExc_ValueError
,
262 "signal number out of range");
265 old_handler
= Handlers
[sig_num
].func
;
266 Py_INCREF(old_handler
);
270 static char getsignal_doc
[] =
271 "getsignal(sig) -> action\n\
273 Return the current action for the given signal. The return value can be:\n\
274 SIG_IGN -- if the signal is being ignored\n\
275 SIG_DFL -- if the default action for the signal is in effect\n\
276 None -- if an unknown handler is in effect\n\
277 anything else -- the callable Python object used as a handler\n\
281 /* List of functions defined in the module */
282 static PyMethodDef signal_methods
[] = {
284 {"alarm", signal_alarm
, METH_OLDARGS
, alarm_doc
},
286 {"signal", signal_signal
, METH_OLDARGS
, signal_doc
},
287 {"getsignal", signal_getsignal
, METH_OLDARGS
, getsignal_doc
},
289 {"pause", signal_pause
, METH_OLDARGS
, pause_doc
},
291 {"default_int_handler", signal_default_int_handler
,
292 METH_OLDARGS
, default_int_handler_doc
},
293 {NULL
, NULL
} /* sentinel */
297 static char module_doc
[] =
298 "This module provides mechanisms to use signal handlers in Python.\n\
302 alarm() -- cause SIGALRM after a specified time [Unix only]\n\
303 signal() -- set the action for a given signal\n\
304 getsignal() -- get the signal action for a given signal\n\
305 pause() -- wait until a signal arrives [Unix only]\n\
306 default_int_handler() -- default SIGINT handler\n\
310 SIG_DFL -- used to refer to the system default handler\n\
311 SIG_IGN -- used to ignore the signal\n\
312 NSIG -- number of defined signals\n\
314 SIGINT, SIGTERM, etc. -- signal numbers\n\
316 *** IMPORTANT NOTICE ***\n\
317 A signal handler function is called with two arguments:\n\
318 the first is the signal number, the second is the interrupted stack frame.";
327 main_thread
= PyThread_get_thread_ident();
331 /* Create the module and add the functions */
332 m
= Py_InitModule3("signal", signal_methods
, module_doc
);
334 /* Add some symbolic constants to the module */
335 d
= PyModule_GetDict(m
);
337 x
= DefaultHandler
= PyLong_FromVoidPtr((void *)SIG_DFL
);
338 if (!x
|| PyDict_SetItemString(d
, "SIG_DFL", x
) < 0)
341 x
= IgnoreHandler
= PyLong_FromVoidPtr((void *)SIG_IGN
);
342 if (!x
|| PyDict_SetItemString(d
, "SIG_IGN", x
) < 0)
345 x
= PyInt_FromLong((long)NSIG
);
346 if (!x
|| PyDict_SetItemString(d
, "NSIG", x
) < 0)
350 x
= IntHandler
= PyDict_GetItemString(d
, "default_int_handler");
353 Py_INCREF(IntHandler
);
355 Handlers
[0].tripped
= 0;
356 for (i
= 1; i
< NSIG
; i
++) {
359 Handlers
[i
].tripped
= 0;
361 Handlers
[i
].func
= DefaultHandler
;
362 else if (t
== SIG_IGN
)
363 Handlers
[i
].func
= IgnoreHandler
;
365 Handlers
[i
].func
= Py_None
; /* None of our business */
366 Py_INCREF(Handlers
[i
].func
);
368 if (Handlers
[SIGINT
].func
== DefaultHandler
) {
369 /* Install default int handler */
370 Py_INCREF(IntHandler
);
371 Py_DECREF(Handlers
[SIGINT
].func
);
372 Handlers
[SIGINT
].func
= IntHandler
;
373 old_siginthandler
= PyOS_setsig(SIGINT
, &signal_handler
);
377 x
= PyInt_FromLong(SIGHUP
);
378 PyDict_SetItemString(d
, "SIGHUP", x
);
382 x
= PyInt_FromLong(SIGINT
);
383 PyDict_SetItemString(d
, "SIGINT", x
);
387 x
= PyInt_FromLong(SIGQUIT
);
388 PyDict_SetItemString(d
, "SIGQUIT", x
);
392 x
= PyInt_FromLong(SIGILL
);
393 PyDict_SetItemString(d
, "SIGILL", x
);
397 x
= PyInt_FromLong(SIGTRAP
);
398 PyDict_SetItemString(d
, "SIGTRAP", x
);
402 x
= PyInt_FromLong(SIGIOT
);
403 PyDict_SetItemString(d
, "SIGIOT", x
);
407 x
= PyInt_FromLong(SIGABRT
);
408 PyDict_SetItemString(d
, "SIGABRT", x
);
412 x
= PyInt_FromLong(SIGEMT
);
413 PyDict_SetItemString(d
, "SIGEMT", x
);
417 x
= PyInt_FromLong(SIGFPE
);
418 PyDict_SetItemString(d
, "SIGFPE", x
);
422 x
= PyInt_FromLong(SIGKILL
);
423 PyDict_SetItemString(d
, "SIGKILL", x
);
427 x
= PyInt_FromLong(SIGBUS
);
428 PyDict_SetItemString(d
, "SIGBUS", x
);
432 x
= PyInt_FromLong(SIGSEGV
);
433 PyDict_SetItemString(d
, "SIGSEGV", x
);
437 x
= PyInt_FromLong(SIGSYS
);
438 PyDict_SetItemString(d
, "SIGSYS", x
);
442 x
= PyInt_FromLong(SIGPIPE
);
443 PyDict_SetItemString(d
, "SIGPIPE", x
);
447 x
= PyInt_FromLong(SIGALRM
);
448 PyDict_SetItemString(d
, "SIGALRM", x
);
452 x
= PyInt_FromLong(SIGTERM
);
453 PyDict_SetItemString(d
, "SIGTERM", x
);
457 x
= PyInt_FromLong(SIGUSR1
);
458 PyDict_SetItemString(d
, "SIGUSR1", x
);
462 x
= PyInt_FromLong(SIGUSR2
);
463 PyDict_SetItemString(d
, "SIGUSR2", x
);
467 x
= PyInt_FromLong(SIGCLD
);
468 PyDict_SetItemString(d
, "SIGCLD", x
);
472 x
= PyInt_FromLong(SIGCHLD
);
473 PyDict_SetItemString(d
, "SIGCHLD", x
);
477 x
= PyInt_FromLong(SIGPWR
);
478 PyDict_SetItemString(d
, "SIGPWR", x
);
482 x
= PyInt_FromLong(SIGIO
);
483 PyDict_SetItemString(d
, "SIGIO", x
);
487 x
= PyInt_FromLong(SIGURG
);
488 PyDict_SetItemString(d
, "SIGURG", x
);
492 x
= PyInt_FromLong(SIGWINCH
);
493 PyDict_SetItemString(d
, "SIGWINCH", x
);
497 x
= PyInt_FromLong(SIGPOLL
);
498 PyDict_SetItemString(d
, "SIGPOLL", x
);
502 x
= PyInt_FromLong(SIGSTOP
);
503 PyDict_SetItemString(d
, "SIGSTOP", x
);
507 x
= PyInt_FromLong(SIGTSTP
);
508 PyDict_SetItemString(d
, "SIGTSTP", x
);
512 x
= PyInt_FromLong(SIGCONT
);
513 PyDict_SetItemString(d
, "SIGCONT", x
);
517 x
= PyInt_FromLong(SIGTTIN
);
518 PyDict_SetItemString(d
, "SIGTTIN", x
);
522 x
= PyInt_FromLong(SIGTTOU
);
523 PyDict_SetItemString(d
, "SIGTTOU", x
);
527 x
= PyInt_FromLong(SIGVTALRM
);
528 PyDict_SetItemString(d
, "SIGVTALRM", x
);
532 x
= PyInt_FromLong(SIGPROF
);
533 PyDict_SetItemString(d
, "SIGPROF", x
);
537 x
= PyInt_FromLong(SIGXCPU
);
538 PyDict_SetItemString(d
, "SIGXCPU", x
);
542 x
= PyInt_FromLong(SIGXFSZ
);
543 PyDict_SetItemString(d
, "SIGXFSZ", x
);
546 if (!PyErr_Occurred())
549 /* Check for errors */
560 PyOS_setsig(SIGINT
, old_siginthandler
);
561 old_siginthandler
= SIG_DFL
;
563 for (i
= 1; i
< NSIG
; i
++) {
564 func
= Handlers
[i
].func
;
565 Handlers
[i
].tripped
= 0;
566 Handlers
[i
].func
= NULL
;
567 if (i
!= SIGINT
&& func
!= NULL
&& func
!= Py_None
&&
568 func
!= DefaultHandler
&& func
!= IgnoreHandler
)
569 PyOS_setsig(i
, SIG_DFL
);
573 Py_XDECREF(IntHandler
);
575 Py_XDECREF(DefaultHandler
);
576 DefaultHandler
= NULL
;
577 Py_XDECREF(IgnoreHandler
);
578 IgnoreHandler
= NULL
;
582 /* Declared in pyerrors.h */
584 PyErr_CheckSignals(void)
592 if (PyThread_get_thread_ident() != main_thread
)
595 if (!(f
= PyEval_GetFrame()))
598 for (i
= 1; i
< NSIG
; i
++) {
599 if (Handlers
[i
].tripped
) {
600 PyObject
*result
= NULL
;
601 PyObject
*arglist
= Py_BuildValue("(iO)", i
, f
);
602 Handlers
[i
].tripped
= 0;
605 result
= PyEval_CallObject(Handlers
[i
].func
,
620 /* Replacements for intrcheck.c functionality
621 * Declared in pyerrors.h
624 PyErr_SetInterrupt(void)
627 Handlers
[SIGINT
].tripped
= 1;
628 Py_AddPendingCall((int (*)(void *))PyErr_CheckSignals
, NULL
);
632 PyOS_InitInterrupts(void)
635 _PyImport_FixupExtension("signal", "signal");
639 PyOS_FiniInterrupts(void)
645 PyOS_InterruptOccurred(void)
647 if (Handlers
[SIGINT
].tripped
) {
649 if (PyThread_get_thread_ident() != main_thread
)
652 Handlers
[SIGINT
].tripped
= 0;
662 PyEval_ReInitThreads();
663 main_thread
= PyThread_get_thread_ident();