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 static PyOS_sighandler_t old_siginthandler
= SIG_DFL
;
92 signal_default_int_handler(PyObject
*self
, PyObject
*args
)
94 PyErr_SetNone(PyExc_KeyboardInterrupt
);
98 static char default_int_handler_doc
[] =
99 "default_int_handler(...)\n\
101 The default handler for SIGINT instated by Python.\n\
102 It raises KeyboardInterrupt.";
106 checksignals_witharg(void * unused
)
108 return PyErr_CheckSignals();
112 signal_handler(int sig_num
)
116 if (PyThread_get_thread_ident() != main_thread
) {
117 pth_raise(*(pth_t
*) main_thread
, sig_num
);
121 /* See NOTES section above */
122 if (getpid() == main_pid
) {
125 Handlers
[sig_num
].tripped
= 1;
126 Py_AddPendingCall(checksignals_witharg
, NULL
);
131 if (sig_num
== SIGCHLD
) {
132 /* To avoid infinite recursion, this signal remains
133 reset until explicit re-instated.
134 Don't clear the 'func' field as it is our pointer
135 to the Python handler... */
139 #ifdef HAVE_SIGINTERRUPT
140 siginterrupt(sig_num
, 1);
142 PyOS_setsig(sig_num
, signal_handler
);
148 signal_alarm(PyObject
*self
, PyObject
*args
)
151 if (!PyArg_Parse(args
, "i", &t
))
153 /* alarm() returns the number of seconds remaining */
154 return PyInt_FromLong(alarm(t
));
157 static char alarm_doc
[] =
160 Arrange for SIGALRM to arrive after the given number of seconds.";
165 signal_pause(PyObject
*self
, PyObject
*args
)
167 if (!PyArg_NoArgs(args
))
170 Py_BEGIN_ALLOW_THREADS
173 /* make sure that any exceptions that got raised are propagated
176 if (PyErr_CheckSignals())
182 static char pause_doc
[] =
185 Wait until a signal arrives.";
191 signal_signal(PyObject
*self
, PyObject
*args
)
195 PyObject
*old_handler
;
197 if (!PyArg_Parse(args
, "(iO)", &sig_num
, &obj
))
200 if (PyThread_get_thread_ident() != main_thread
) {
201 PyErr_SetString(PyExc_ValueError
,
202 "signal only works in main thread");
206 if (sig_num
< 1 || sig_num
>= NSIG
) {
207 PyErr_SetString(PyExc_ValueError
,
208 "signal number out of range");
211 if (obj
== IgnoreHandler
)
213 else if (obj
== DefaultHandler
)
215 else if (!PyCallable_Check(obj
)) {
216 PyErr_SetString(PyExc_TypeError
,
217 "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
221 func
= signal_handler
;
222 #ifdef HAVE_SIGINTERRUPT
223 siginterrupt(sig_num
, 1);
225 if (PyOS_setsig(sig_num
, func
) == SIG_ERR
) {
226 PyErr_SetFromErrno(PyExc_RuntimeError
);
229 old_handler
= Handlers
[sig_num
].func
;
230 Handlers
[sig_num
].tripped
= 0;
232 Handlers
[sig_num
].func
= obj
;
236 static char signal_doc
[] =
237 "signal(sig, action) -> action\n\
239 Set the action for the given signal. The action can be SIG_DFL,\n\
240 SIG_IGN, or a callable Python object. The previous action is\n\
241 returned. See getsignal() for possible return values.\n\
243 *** IMPORTANT NOTICE ***\n\
244 A signal handler function is called with two arguments:\n\
245 the first is the signal number, the second is the interrupted stack frame.";
249 signal_getsignal(PyObject
*self
, PyObject
*args
)
252 PyObject
*old_handler
;
253 if (!PyArg_Parse(args
, "i", &sig_num
))
255 if (sig_num
< 1 || sig_num
>= NSIG
) {
256 PyErr_SetString(PyExc_ValueError
,
257 "signal number out of range");
260 old_handler
= Handlers
[sig_num
].func
;
261 Py_INCREF(old_handler
);
265 static char getsignal_doc
[] =
266 "getsignal(sig) -> action\n\
268 Return the current action for the given signal. The return value can be:\n\
269 SIG_IGN -- if the signal is being ignored\n\
270 SIG_DFL -- if the default action for the signal is in effect\n\
271 None -- if an unknown handler is in effect\n\
272 anything else -- the callable Python object used as a handler\n\
276 /* List of functions defined in the module */
277 static PyMethodDef signal_methods
[] = {
279 {"alarm", signal_alarm
, METH_OLDARGS
, alarm_doc
},
281 {"signal", signal_signal
, METH_OLDARGS
, signal_doc
},
282 {"getsignal", signal_getsignal
, METH_OLDARGS
, getsignal_doc
},
284 {"pause", signal_pause
, METH_OLDARGS
, pause_doc
},
286 {"default_int_handler", signal_default_int_handler
,
287 METH_OLDARGS
, default_int_handler_doc
},
288 {NULL
, NULL
} /* sentinel */
292 static char module_doc
[] =
293 "This module provides mechanisms to use signal handlers in Python.\n\
297 alarm() -- cause SIGALRM after a specified time [Unix only]\n\
298 signal() -- set the action for a given signal\n\
299 getsignal() -- get the signal action for a given signal\n\
300 pause() -- wait until a signal arrives [Unix only]\n\
301 default_int_handler() -- default SIGINT handler\n\
305 SIG_DFL -- used to refer to the system default handler\n\
306 SIG_IGN -- used to ignore the signal\n\
307 NSIG -- number of defined signals\n\
309 SIGINT, SIGTERM, etc. -- signal numbers\n\
311 *** IMPORTANT NOTICE ***\n\
312 A signal handler function is called with two arguments:\n\
313 the first is the signal number, the second is the interrupted stack frame.";
322 main_thread
= PyThread_get_thread_ident();
326 /* Create the module and add the functions */
327 m
= Py_InitModule3("signal", signal_methods
, module_doc
);
329 /* Add some symbolic constants to the module */
330 d
= PyModule_GetDict(m
);
332 x
= DefaultHandler
= PyLong_FromVoidPtr((void *)SIG_DFL
);
333 if (!x
|| PyDict_SetItemString(d
, "SIG_DFL", x
) < 0)
336 x
= IgnoreHandler
= PyLong_FromVoidPtr((void *)SIG_IGN
);
337 if (!x
|| PyDict_SetItemString(d
, "SIG_IGN", x
) < 0)
340 x
= PyInt_FromLong((long)NSIG
);
341 if (!x
|| PyDict_SetItemString(d
, "NSIG", x
) < 0)
345 x
= IntHandler
= PyDict_GetItemString(d
, "default_int_handler");
348 Py_INCREF(IntHandler
);
350 Handlers
[0].tripped
= 0;
351 for (i
= 1; i
< NSIG
; i
++) {
354 Handlers
[i
].tripped
= 0;
356 Handlers
[i
].func
= DefaultHandler
;
357 else if (t
== SIG_IGN
)
358 Handlers
[i
].func
= IgnoreHandler
;
360 Handlers
[i
].func
= Py_None
; /* None of our business */
361 Py_INCREF(Handlers
[i
].func
);
363 if (Handlers
[SIGINT
].func
== DefaultHandler
) {
364 /* Install default int handler */
365 Py_INCREF(IntHandler
);
366 Py_DECREF(Handlers
[SIGINT
].func
);
367 Handlers
[SIGINT
].func
= IntHandler
;
368 old_siginthandler
= PyOS_setsig(SIGINT
, &signal_handler
);
372 x
= PyInt_FromLong(SIGHUP
);
373 PyDict_SetItemString(d
, "SIGHUP", x
);
377 x
= PyInt_FromLong(SIGINT
);
378 PyDict_SetItemString(d
, "SIGINT", x
);
382 x
= PyInt_FromLong(SIGQUIT
);
383 PyDict_SetItemString(d
, "SIGQUIT", x
);
387 x
= PyInt_FromLong(SIGILL
);
388 PyDict_SetItemString(d
, "SIGILL", x
);
392 x
= PyInt_FromLong(SIGTRAP
);
393 PyDict_SetItemString(d
, "SIGTRAP", x
);
397 x
= PyInt_FromLong(SIGIOT
);
398 PyDict_SetItemString(d
, "SIGIOT", x
);
402 x
= PyInt_FromLong(SIGABRT
);
403 PyDict_SetItemString(d
, "SIGABRT", x
);
407 x
= PyInt_FromLong(SIGEMT
);
408 PyDict_SetItemString(d
, "SIGEMT", x
);
412 x
= PyInt_FromLong(SIGFPE
);
413 PyDict_SetItemString(d
, "SIGFPE", x
);
417 x
= PyInt_FromLong(SIGKILL
);
418 PyDict_SetItemString(d
, "SIGKILL", x
);
422 x
= PyInt_FromLong(SIGBUS
);
423 PyDict_SetItemString(d
, "SIGBUS", x
);
427 x
= PyInt_FromLong(SIGSEGV
);
428 PyDict_SetItemString(d
, "SIGSEGV", x
);
432 x
= PyInt_FromLong(SIGSYS
);
433 PyDict_SetItemString(d
, "SIGSYS", x
);
437 x
= PyInt_FromLong(SIGPIPE
);
438 PyDict_SetItemString(d
, "SIGPIPE", x
);
442 x
= PyInt_FromLong(SIGALRM
);
443 PyDict_SetItemString(d
, "SIGALRM", x
);
447 x
= PyInt_FromLong(SIGTERM
);
448 PyDict_SetItemString(d
, "SIGTERM", x
);
452 x
= PyInt_FromLong(SIGUSR1
);
453 PyDict_SetItemString(d
, "SIGUSR1", x
);
457 x
= PyInt_FromLong(SIGUSR2
);
458 PyDict_SetItemString(d
, "SIGUSR2", x
);
462 x
= PyInt_FromLong(SIGCLD
);
463 PyDict_SetItemString(d
, "SIGCLD", x
);
467 x
= PyInt_FromLong(SIGCHLD
);
468 PyDict_SetItemString(d
, "SIGCHLD", x
);
472 x
= PyInt_FromLong(SIGPWR
);
473 PyDict_SetItemString(d
, "SIGPWR", x
);
477 x
= PyInt_FromLong(SIGIO
);
478 PyDict_SetItemString(d
, "SIGIO", x
);
482 x
= PyInt_FromLong(SIGURG
);
483 PyDict_SetItemString(d
, "SIGURG", x
);
487 x
= PyInt_FromLong(SIGWINCH
);
488 PyDict_SetItemString(d
, "SIGWINCH", x
);
492 x
= PyInt_FromLong(SIGPOLL
);
493 PyDict_SetItemString(d
, "SIGPOLL", x
);
497 x
= PyInt_FromLong(SIGSTOP
);
498 PyDict_SetItemString(d
, "SIGSTOP", x
);
502 x
= PyInt_FromLong(SIGTSTP
);
503 PyDict_SetItemString(d
, "SIGTSTP", x
);
507 x
= PyInt_FromLong(SIGCONT
);
508 PyDict_SetItemString(d
, "SIGCONT", x
);
512 x
= PyInt_FromLong(SIGTTIN
);
513 PyDict_SetItemString(d
, "SIGTTIN", x
);
517 x
= PyInt_FromLong(SIGTTOU
);
518 PyDict_SetItemString(d
, "SIGTTOU", x
);
522 x
= PyInt_FromLong(SIGVTALRM
);
523 PyDict_SetItemString(d
, "SIGVTALRM", x
);
527 x
= PyInt_FromLong(SIGPROF
);
528 PyDict_SetItemString(d
, "SIGPROF", x
);
532 x
= PyInt_FromLong(SIGXCPU
);
533 PyDict_SetItemString(d
, "SIGXCPU", x
);
537 x
= PyInt_FromLong(SIGXFSZ
);
538 PyDict_SetItemString(d
, "SIGXFSZ", x
);
541 if (!PyErr_Occurred())
544 /* Check for errors */
555 PyOS_setsig(SIGINT
, old_siginthandler
);
556 old_siginthandler
= SIG_DFL
;
558 for (i
= 1; i
< NSIG
; i
++) {
559 func
= Handlers
[i
].func
;
560 Handlers
[i
].tripped
= 0;
561 Handlers
[i
].func
= NULL
;
562 if (i
!= SIGINT
&& func
!= NULL
&& func
!= Py_None
&&
563 func
!= DefaultHandler
&& func
!= IgnoreHandler
)
564 PyOS_setsig(i
, SIG_DFL
);
568 Py_XDECREF(IntHandler
);
570 Py_XDECREF(DefaultHandler
);
571 DefaultHandler
= NULL
;
572 Py_XDECREF(IgnoreHandler
);
573 IgnoreHandler
= NULL
;
577 /* Declared in pyerrors.h */
579 PyErr_CheckSignals(void)
587 if (PyThread_get_thread_ident() != main_thread
)
590 if (!(f
= PyEval_GetFrame()))
593 for (i
= 1; i
< NSIG
; i
++) {
594 if (Handlers
[i
].tripped
) {
595 PyObject
*result
= NULL
;
596 PyObject
*arglist
= Py_BuildValue("(iO)", i
, f
);
597 Handlers
[i
].tripped
= 0;
600 result
= PyEval_CallObject(Handlers
[i
].func
,
615 /* Replacements for intrcheck.c functionality
616 * Declared in pyerrors.h
619 PyErr_SetInterrupt(void)
622 Handlers
[SIGINT
].tripped
= 1;
623 Py_AddPendingCall((int (*)(void *))PyErr_CheckSignals
, NULL
);
627 PyOS_InitInterrupts(void)
630 _PyImport_FixupExtension("signal", "signal");
634 PyOS_FiniInterrupts(void)
640 PyOS_InterruptOccurred(void)
642 if (Handlers
[SIGINT
].tripped
) {
644 if (PyThread_get_thread_ident() != main_thread
)
647 Handlers
[SIGINT
].tripped
= 0;
657 PyEval_ReInitThreads();
658 main_thread
= PyThread_get_thread_ident();