2 /* Signal module -- many thanks to Lance Ellinghaus */
4 /* XXX Signals should be recorded per thread, now we have thread state. */
16 #ifdef HAVE_SYS_TIME_H
21 #define SIG_ERR ((PyOS_sighandler_t)(-1))
24 #if defined(PYOS_OS2) && !defined(PYCC_GCC)
31 # define NSIG _NSIG /* For BSD/SysV */
32 # elif defined(_SIGMAX)
33 # define NSIG (_SIGMAX + 1) /* For QNX */
34 # elif defined(SIGMAX)
35 # define NSIG (SIGMAX + 1) /* For djgpp */
37 # define NSIG 64 /* Use a reasonable default value */
43 NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS
45 When threads are supported, we want the following semantics:
47 - only the main thread can set a signal handler
48 - any thread can get a signal handler
49 - signals are only delivered to the main thread
51 I.e. we don't support "synchronous signals" like SIGFPE (catching
52 this doesn't make much sense in Python anyway) nor do we support
53 signals as a means of inter-thread communication, since not all
54 thread implementations support that (at least our thread library
57 We still have the problem that in some implementations signals
58 generated by the keyboard (e.g. SIGINT) are delivered to all
59 threads (e.g. SGI), while in others (e.g. Solaris) such signals are
60 delivered to one random thread (an intermediate possibility would
61 be to deliver it to the main thread -- POSIX?). For now, we have
62 a working implementation that works in all three cases -- the
63 handler ignores signals if getpid() isn't the same as in the main
64 thread. XXX This is a hack.
66 GNU pth is a user-space threading library, and as such, all threads
67 run within the same process. In this case, if the currently running
68 thread is not the main_thread, send the signal to the main_thread.
72 #include <sys/types.h> /* For pid_t */
74 static long main_thread
;
75 static pid_t main_pid
;
83 static sig_atomic_t wakeup_fd
= -1;
85 /* Speed up sigcheck() when none tripped */
86 static volatile sig_atomic_t is_tripped
= 0;
88 static PyObject
*DefaultHandler
;
89 static PyObject
*IgnoreHandler
;
90 static PyObject
*IntHandler
;
92 /* On Solaris 8, gcc will produce a warning that the function
93 declaration is not a prototype. This is caused by the definition of
94 SIG_DFL as (void (*)())0; the correct declaration would have been
97 static PyOS_sighandler_t old_siginthandler
= SIG_DFL
;
100 static PyObject
*ItimerError
;
102 /* auxiliary functions for setitimer/getitimer */
104 timeval_from_double(double d
, struct timeval
*tv
)
106 tv
->tv_sec
= floor(d
);
107 tv
->tv_usec
= fmod(d
, 1.0) * 1000000.0;
111 double_from_timeval(struct timeval
*tv
)
113 return tv
->tv_sec
+ (double)(tv
->tv_usec
/ 1000000.0);
117 itimer_retval(struct itimerval
*iv
)
125 if(!(v
= PyFloat_FromDouble(double_from_timeval(&iv
->it_value
)))) {
130 PyTuple_SET_ITEM(r
, 0, v
);
132 if(!(v
= PyFloat_FromDouble(double_from_timeval(&iv
->it_interval
)))) {
137 PyTuple_SET_ITEM(r
, 1, v
);
144 signal_default_int_handler(PyObject
*self
, PyObject
*args
)
146 PyErr_SetNone(PyExc_KeyboardInterrupt
);
150 PyDoc_STRVAR(default_int_handler_doc
,
151 "default_int_handler(...)\n\
153 The default handler for SIGINT installed by Python.\n\
154 It raises KeyboardInterrupt.");
158 checksignals_witharg(void * unused
)
160 return PyErr_CheckSignals();
164 signal_handler(int sig_num
)
168 if (PyThread_get_thread_ident() != main_thread
) {
169 pth_raise(*(pth_t
*) main_thread
, sig_num
);
173 /* See NOTES section above */
174 if (getpid() == main_pid
) {
176 Handlers
[sig_num
].tripped
= 1;
177 /* Set is_tripped after setting .tripped, as it gets
178 cleared in PyErr_CheckSignals() before .tripped. */
180 Py_AddPendingCall(checksignals_witharg
, NULL
);
182 write(wakeup_fd
, "\0", 1);
187 if (sig_num
== SIGCHLD
) {
188 /* To avoid infinite recursion, this signal remains
189 reset until explicit re-instated.
190 Don't clear the 'func' field as it is our pointer
191 to the Python handler... */
195 PyOS_setsig(sig_num
, signal_handler
);
201 signal_alarm(PyObject
*self
, PyObject
*args
)
204 if (!PyArg_ParseTuple(args
, "i:alarm", &t
))
206 /* alarm() returns the number of seconds remaining */
207 return PyInt_FromLong((long)alarm(t
));
210 PyDoc_STRVAR(alarm_doc
,
213 Arrange for SIGALRM to arrive after the given number of seconds.");
218 signal_pause(PyObject
*self
)
220 Py_BEGIN_ALLOW_THREADS
223 /* make sure that any exceptions that got raised are propagated
226 if (PyErr_CheckSignals())
232 PyDoc_STRVAR(pause_doc
,
235 Wait until a signal arrives.");
241 signal_signal(PyObject
*self
, PyObject
*args
)
245 PyObject
*old_handler
;
247 if (!PyArg_ParseTuple(args
, "iO:signal", &sig_num
, &obj
))
250 if (PyThread_get_thread_ident() != main_thread
) {
251 PyErr_SetString(PyExc_ValueError
,
252 "signal only works in main thread");
256 if (sig_num
< 1 || sig_num
>= NSIG
) {
257 PyErr_SetString(PyExc_ValueError
,
258 "signal number out of range");
261 if (obj
== IgnoreHandler
)
263 else if (obj
== DefaultHandler
)
265 else if (!PyCallable_Check(obj
)) {
266 PyErr_SetString(PyExc_TypeError
,
267 "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
271 func
= signal_handler
;
272 if (PyOS_setsig(sig_num
, func
) == SIG_ERR
) {
273 PyErr_SetFromErrno(PyExc_RuntimeError
);
276 old_handler
= Handlers
[sig_num
].func
;
277 Handlers
[sig_num
].tripped
= 0;
279 Handlers
[sig_num
].func
= obj
;
283 PyDoc_STRVAR(signal_doc
,
284 "signal(sig, action) -> action\n\
286 Set the action for the given signal. The action can be SIG_DFL,\n\
287 SIG_IGN, or a callable Python object. The previous action is\n\
288 returned. See getsignal() for possible return values.\n\
290 *** IMPORTANT NOTICE ***\n\
291 A signal handler function is called with two arguments:\n\
292 the first is the signal number, the second is the interrupted stack frame.");
296 signal_getsignal(PyObject
*self
, PyObject
*args
)
299 PyObject
*old_handler
;
300 if (!PyArg_ParseTuple(args
, "i:getsignal", &sig_num
))
302 if (sig_num
< 1 || sig_num
>= NSIG
) {
303 PyErr_SetString(PyExc_ValueError
,
304 "signal number out of range");
307 old_handler
= Handlers
[sig_num
].func
;
308 Py_INCREF(old_handler
);
312 PyDoc_STRVAR(getsignal_doc
,
313 "getsignal(sig) -> action\n\
315 Return the current action for the given signal. The return value can be:\n\
316 SIG_IGN -- if the signal is being ignored\n\
317 SIG_DFL -- if the default action for the signal is in effect\n\
318 None -- if an unknown handler is in effect\n\
319 anything else -- the callable Python object used as a handler");
321 #ifdef HAVE_SIGINTERRUPT
322 PyDoc_STRVAR(siginterrupt_doc
,
323 "siginterrupt(sig, flag) -> None\n\
324 change system call restart behaviour: if flag is False, system calls\n\
325 will be restarted when interrupted by signal sig, else system calls\n\
326 will be interrupted.");
329 signal_siginterrupt(PyObject
*self
, PyObject
*args
)
334 if (!PyArg_ParseTuple(args
, "ii:siginterrupt", &sig_num
, &flag
))
336 if (sig_num
< 1 || sig_num
>= NSIG
) {
337 PyErr_SetString(PyExc_ValueError
,
338 "signal number out of range");
341 if (siginterrupt(sig_num
, flag
)<0) {
342 PyErr_SetFromErrno(PyExc_RuntimeError
);
353 signal_set_wakeup_fd(PyObject
*self
, PyObject
*args
)
357 if (!PyArg_ParseTuple(args
, "i:set_wakeup_fd", &fd
))
360 if (PyThread_get_thread_ident() != main_thread
) {
361 PyErr_SetString(PyExc_ValueError
,
362 "set_wakeup_fd only works in main thread");
366 if (fd
!= -1 && fstat(fd
, &buf
) != 0) {
367 PyErr_SetString(PyExc_ValueError
, "invalid fd");
372 return PyLong_FromLong(old_fd
);
375 PyDoc_STRVAR(set_wakeup_fd_doc
,
376 "set_wakeup_fd(fd) -> fd\n\
378 Sets the fd to be written to (with '\\0') when a signal\n\
379 comes in. A library can use this to wakeup select or poll.\n\
380 The previous fd is returned.\n\
382 The fd must be non-blocking.");
384 /* C API for the same, without all the error checking */
386 PySignal_SetWakeupFd(int fd
)
388 int old_fd
= wakeup_fd
;
396 #ifdef HAVE_SETITIMER
398 signal_setitimer(PyObject
*self
, PyObject
*args
)
403 struct itimerval
new, old
;
405 if(!PyArg_ParseTuple(args
, "id|d:setitimer", &which
, &first
, &interval
))
408 timeval_from_double(first
, &new.it_value
);
409 timeval_from_double(interval
, &new.it_interval
);
410 /* Let OS check "which" value */
411 if (setitimer(which
, &new, &old
) != 0) {
412 PyErr_SetFromErrno(ItimerError
);
416 return itimer_retval(&old
);
419 PyDoc_STRVAR(setitimer_doc
,
420 "setitimer(which, seconds[, interval])\n\
422 Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL\n\
423 or ITIMER_PROF) to fire after value seconds and after\n\
424 that every interval seconds.\n\
425 The itimer can be cleared by setting seconds to zero.\n\
427 Returns old values as a tuple: (delay, interval).");
431 #ifdef HAVE_GETITIMER
433 signal_getitimer(PyObject
*self
, PyObject
*args
)
436 struct itimerval old
;
438 if (!PyArg_ParseTuple(args
, "i:getitimer", &which
))
441 if (getitimer(which
, &old
) != 0) {
442 PyErr_SetFromErrno(ItimerError
);
446 return itimer_retval(&old
);
449 PyDoc_STRVAR(getitimer_doc
,
452 Returns current value of given itimer.");
456 /* List of functions defined in the module */
457 static PyMethodDef signal_methods
[] = {
459 {"alarm", signal_alarm
, METH_VARARGS
, alarm_doc
},
461 #ifdef HAVE_SETITIMER
462 {"setitimer", signal_setitimer
, METH_VARARGS
, setitimer_doc
},
464 #ifdef HAVE_GETITIMER
465 {"getitimer", signal_getitimer
, METH_VARARGS
, getitimer_doc
},
467 {"signal", signal_signal
, METH_VARARGS
, signal_doc
},
468 {"getsignal", signal_getsignal
, METH_VARARGS
, getsignal_doc
},
469 {"set_wakeup_fd", signal_set_wakeup_fd
, METH_VARARGS
, set_wakeup_fd_doc
},
470 #ifdef HAVE_SIGINTERRUPT
471 {"siginterrupt", signal_siginterrupt
, METH_VARARGS
, siginterrupt_doc
},
474 {"pause", (PyCFunction
)signal_pause
,
475 METH_NOARGS
,pause_doc
},
477 {"default_int_handler", signal_default_int_handler
,
478 METH_VARARGS
, default_int_handler_doc
},
479 {NULL
, NULL
} /* sentinel */
483 PyDoc_STRVAR(module_doc
,
484 "This module provides mechanisms to use signal handlers in Python.\n\
488 alarm() -- cause SIGALRM after a specified time [Unix only]\n\
489 setitimer() -- cause a signal (described below) after a specified\n\
490 float time and the timer may restart then [Unix only]\n\
491 getitimer() -- get current value of timer [Unix only]\n\
492 signal() -- set the action for a given signal\n\
493 getsignal() -- get the signal action for a given signal\n\
494 pause() -- wait until a signal arrives [Unix only]\n\
495 default_int_handler() -- default SIGINT handler\n\
498 SIG_DFL -- used to refer to the system default handler\n\
499 SIG_IGN -- used to ignore the signal\n\
500 NSIG -- number of defined signals\n\
501 SIGINT, SIGTERM, etc. -- signal numbers\n\
504 ITIMER_REAL -- decrements in real time, and delivers SIGALRM upon\n\
506 ITIMER_VIRTUAL -- decrements only when the process is executing,\n\
507 and delivers SIGVTALRM upon expiration\n\
508 ITIMER_PROF -- decrements both when the process is executing and\n\
509 when the system is executing on behalf of the process.\n\
510 Coupled with ITIMER_VIRTUAL, this timer is usually\n\
511 used to profile the time spent by the application\n\
512 in user and kernel space. SIGPROF is delivered upon\n\
515 *** IMPORTANT NOTICE ***\n\
516 A signal handler function is called with two arguments:\n\
517 the first is the signal number, the second is the interrupted stack frame.");
526 main_thread
= PyThread_get_thread_ident();
530 /* Create the module and add the functions */
531 m
= Py_InitModule3("signal", signal_methods
, module_doc
);
535 /* Add some symbolic constants to the module */
536 d
= PyModule_GetDict(m
);
538 x
= DefaultHandler
= PyLong_FromVoidPtr((void *)SIG_DFL
);
539 if (!x
|| PyDict_SetItemString(d
, "SIG_DFL", x
) < 0)
542 x
= IgnoreHandler
= PyLong_FromVoidPtr((void *)SIG_IGN
);
543 if (!x
|| PyDict_SetItemString(d
, "SIG_IGN", x
) < 0)
546 x
= PyInt_FromLong((long)NSIG
);
547 if (!x
|| PyDict_SetItemString(d
, "NSIG", x
) < 0)
551 x
= IntHandler
= PyDict_GetItemString(d
, "default_int_handler");
554 Py_INCREF(IntHandler
);
556 Handlers
[0].tripped
= 0;
557 for (i
= 1; i
< NSIG
; i
++) {
560 Handlers
[i
].tripped
= 0;
562 Handlers
[i
].func
= DefaultHandler
;
563 else if (t
== SIG_IGN
)
564 Handlers
[i
].func
= IgnoreHandler
;
566 Handlers
[i
].func
= Py_None
; /* None of our business */
567 Py_INCREF(Handlers
[i
].func
);
569 if (Handlers
[SIGINT
].func
== DefaultHandler
) {
570 /* Install default int handler */
571 Py_INCREF(IntHandler
);
572 Py_DECREF(Handlers
[SIGINT
].func
);
573 Handlers
[SIGINT
].func
= IntHandler
;
574 old_siginthandler
= PyOS_setsig(SIGINT
, signal_handler
);
578 x
= PyInt_FromLong(SIGHUP
);
579 PyDict_SetItemString(d
, "SIGHUP", x
);
583 x
= PyInt_FromLong(SIGINT
);
584 PyDict_SetItemString(d
, "SIGINT", x
);
588 x
= PyInt_FromLong(SIGBREAK
);
589 PyDict_SetItemString(d
, "SIGBREAK", x
);
593 x
= PyInt_FromLong(SIGQUIT
);
594 PyDict_SetItemString(d
, "SIGQUIT", x
);
598 x
= PyInt_FromLong(SIGILL
);
599 PyDict_SetItemString(d
, "SIGILL", x
);
603 x
= PyInt_FromLong(SIGTRAP
);
604 PyDict_SetItemString(d
, "SIGTRAP", x
);
608 x
= PyInt_FromLong(SIGIOT
);
609 PyDict_SetItemString(d
, "SIGIOT", x
);
613 x
= PyInt_FromLong(SIGABRT
);
614 PyDict_SetItemString(d
, "SIGABRT", x
);
618 x
= PyInt_FromLong(SIGEMT
);
619 PyDict_SetItemString(d
, "SIGEMT", x
);
623 x
= PyInt_FromLong(SIGFPE
);
624 PyDict_SetItemString(d
, "SIGFPE", x
);
628 x
= PyInt_FromLong(SIGKILL
);
629 PyDict_SetItemString(d
, "SIGKILL", x
);
633 x
= PyInt_FromLong(SIGBUS
);
634 PyDict_SetItemString(d
, "SIGBUS", x
);
638 x
= PyInt_FromLong(SIGSEGV
);
639 PyDict_SetItemString(d
, "SIGSEGV", x
);
643 x
= PyInt_FromLong(SIGSYS
);
644 PyDict_SetItemString(d
, "SIGSYS", x
);
648 x
= PyInt_FromLong(SIGPIPE
);
649 PyDict_SetItemString(d
, "SIGPIPE", x
);
653 x
= PyInt_FromLong(SIGALRM
);
654 PyDict_SetItemString(d
, "SIGALRM", x
);
658 x
= PyInt_FromLong(SIGTERM
);
659 PyDict_SetItemString(d
, "SIGTERM", x
);
663 x
= PyInt_FromLong(SIGUSR1
);
664 PyDict_SetItemString(d
, "SIGUSR1", x
);
668 x
= PyInt_FromLong(SIGUSR2
);
669 PyDict_SetItemString(d
, "SIGUSR2", x
);
673 x
= PyInt_FromLong(SIGCLD
);
674 PyDict_SetItemString(d
, "SIGCLD", x
);
678 x
= PyInt_FromLong(SIGCHLD
);
679 PyDict_SetItemString(d
, "SIGCHLD", x
);
683 x
= PyInt_FromLong(SIGPWR
);
684 PyDict_SetItemString(d
, "SIGPWR", x
);
688 x
= PyInt_FromLong(SIGIO
);
689 PyDict_SetItemString(d
, "SIGIO", x
);
693 x
= PyInt_FromLong(SIGURG
);
694 PyDict_SetItemString(d
, "SIGURG", x
);
698 x
= PyInt_FromLong(SIGWINCH
);
699 PyDict_SetItemString(d
, "SIGWINCH", x
);
703 x
= PyInt_FromLong(SIGPOLL
);
704 PyDict_SetItemString(d
, "SIGPOLL", x
);
708 x
= PyInt_FromLong(SIGSTOP
);
709 PyDict_SetItemString(d
, "SIGSTOP", x
);
713 x
= PyInt_FromLong(SIGTSTP
);
714 PyDict_SetItemString(d
, "SIGTSTP", x
);
718 x
= PyInt_FromLong(SIGCONT
);
719 PyDict_SetItemString(d
, "SIGCONT", x
);
723 x
= PyInt_FromLong(SIGTTIN
);
724 PyDict_SetItemString(d
, "SIGTTIN", x
);
728 x
= PyInt_FromLong(SIGTTOU
);
729 PyDict_SetItemString(d
, "SIGTTOU", x
);
733 x
= PyInt_FromLong(SIGVTALRM
);
734 PyDict_SetItemString(d
, "SIGVTALRM", x
);
738 x
= PyInt_FromLong(SIGPROF
);
739 PyDict_SetItemString(d
, "SIGPROF", x
);
743 x
= PyInt_FromLong(SIGXCPU
);
744 PyDict_SetItemString(d
, "SIGXCPU", x
);
748 x
= PyInt_FromLong(SIGXFSZ
);
749 PyDict_SetItemString(d
, "SIGXFSZ", x
);
753 x
= PyInt_FromLong(SIGRTMIN
);
754 PyDict_SetItemString(d
, "SIGRTMIN", x
);
758 x
= PyInt_FromLong(SIGRTMAX
);
759 PyDict_SetItemString(d
, "SIGRTMAX", x
);
763 x
= PyInt_FromLong(SIGINFO
);
764 PyDict_SetItemString(d
, "SIGINFO", x
);
769 x
= PyLong_FromLong(ITIMER_REAL
);
770 PyDict_SetItemString(d
, "ITIMER_REAL", x
);
773 #ifdef ITIMER_VIRTUAL
774 x
= PyLong_FromLong(ITIMER_VIRTUAL
);
775 PyDict_SetItemString(d
, "ITIMER_VIRTUAL", x
);
779 x
= PyLong_FromLong(ITIMER_PROF
);
780 PyDict_SetItemString(d
, "ITIMER_PROF", x
);
784 #if defined (HAVE_SETITIMER) || defined (HAVE_GETITIMER)
785 ItimerError
= PyErr_NewException("signal.ItimerError",
786 PyExc_IOError
, NULL
);
787 PyDict_SetItemString(d
, "ItimerError", ItimerError
);
790 if (!PyErr_Occurred())
793 /* Check for errors */
804 PyOS_setsig(SIGINT
, old_siginthandler
);
805 old_siginthandler
= SIG_DFL
;
807 for (i
= 1; i
< NSIG
; i
++) {
808 func
= Handlers
[i
].func
;
809 Handlers
[i
].tripped
= 0;
810 Handlers
[i
].func
= NULL
;
811 if (i
!= SIGINT
&& func
!= NULL
&& func
!= Py_None
&&
812 func
!= DefaultHandler
&& func
!= IgnoreHandler
)
813 PyOS_setsig(i
, SIG_DFL
);
817 Py_XDECREF(IntHandler
);
819 Py_XDECREF(DefaultHandler
);
820 DefaultHandler
= NULL
;
821 Py_XDECREF(IgnoreHandler
);
822 IgnoreHandler
= NULL
;
826 /* Declared in pyerrors.h */
828 PyErr_CheckSignals(void)
837 if (PyThread_get_thread_ident() != main_thread
)
842 * The is_stripped variable is meant to speed up the calls to
843 * PyErr_CheckSignals (both directly or via pending calls) when no
844 * signal has arrived. This variable is set to 1 when a signal arrives
845 * and it is set to 0 here, when we know some signals arrived. This way
846 * we can run the registered handlers with no signals blocked.
848 * NOTE: with this approach we can have a situation where is_tripped is
849 * 1 but we have no more signals to handle (Handlers[i].tripped
850 * is 0 for every signal i). This won't do us any harm (except
851 * we're gonna spent some cycles for nothing). This happens when
852 * we receive a signal i after we zero is_tripped and before we
853 * check Handlers[i].tripped.
857 if (!(f
= (PyObject
*)PyEval_GetFrame()))
860 for (i
= 1; i
< NSIG
; i
++) {
861 if (Handlers
[i
].tripped
) {
862 PyObject
*result
= NULL
;
863 PyObject
*arglist
= Py_BuildValue("(iO)", i
, f
);
864 Handlers
[i
].tripped
= 0;
867 result
= PyEval_CallObject(Handlers
[i
].func
,
882 /* Replacements for intrcheck.c functionality
883 * Declared in pyerrors.h
886 PyErr_SetInterrupt(void)
889 Handlers
[SIGINT
].tripped
= 1;
890 Py_AddPendingCall((int (*)(void *))PyErr_CheckSignals
, NULL
);
894 PyOS_InitInterrupts(void)
897 _PyImport_FixupExtension("signal", "signal");
901 PyOS_FiniInterrupts(void)
907 PyOS_InterruptOccurred(void)
909 if (Handlers
[SIGINT
].tripped
) {
911 if (PyThread_get_thread_ident() != main_thread
)
914 Handlers
[SIGINT
].tripped
= 0;
924 PyEval_ReInitThreads();
925 main_thread
= PyThread_get_thread_ident();
927 _PyImport_ReInitLock();