signalmodule.c revision b42a21df1102a4ca833cf50d7caeda9391a8a54a
1
2/* Signal module -- many thanks to Lance Ellinghaus */
3
4/* XXX Signals should be recorded per thread, now we have thread state. */
5
6#include "Python.h"
7#include "intrcheck.h"
8
9#ifdef MS_WINDOWS
10#include <Windows.h>
11#ifdef HAVE_PROCESS_H
12#include <process.h>
13#endif
14#endif
15
16#include <signal.h>
17
18#include <sys/stat.h>
19#ifdef HAVE_SYS_TIME_H
20#include <sys/time.h>
21#endif
22
23#ifndef SIG_ERR
24#define SIG_ERR ((PyOS_sighandler_t)(-1))
25#endif
26
27#if defined(PYOS_OS2) && !defined(PYCC_GCC)
28#define NSIG 12
29#include <process.h>
30#endif
31
32#ifndef NSIG
33# if defined(_NSIG)
34#  define NSIG _NSIG            /* For BSD/SysV */
35# elif defined(_SIGMAX)
36#  define NSIG (_SIGMAX + 1)    /* For QNX */
37# elif defined(SIGMAX)
38#  define NSIG (SIGMAX + 1)     /* For djgpp */
39# else
40#  define NSIG 64               /* Use a reasonable default value */
41# endif
42#endif
43
44
45/*
46   NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS
47
48   When threads are supported, we want the following semantics:
49
50   - only the main thread can set a signal handler
51   - any thread can get a signal handler
52   - signals are only delivered to the main thread
53
54   I.e. we don't support "synchronous signals" like SIGFPE (catching
55   this doesn't make much sense in Python anyway) nor do we support
56   signals as a means of inter-thread communication, since not all
57   thread implementations support that (at least our thread library
58   doesn't).
59
60   We still have the problem that in some implementations signals
61   generated by the keyboard (e.g. SIGINT) are delivered to all
62   threads (e.g. SGI), while in others (e.g. Solaris) such signals are
63   delivered to one random thread (an intermediate possibility would
64   be to deliver it to the main thread -- POSIX?).  For now, we have
65   a working implementation that works in all three cases -- the
66   handler ignores signals if getpid() isn't the same as in the main
67   thread.  XXX This is a hack.
68
69   GNU pth is a user-space threading library, and as such, all threads
70   run within the same process. In this case, if the currently running
71   thread is not the main_thread, send the signal to the main_thread.
72*/
73
74#ifdef WITH_THREAD
75#include <sys/types.h> /* For pid_t */
76#include "pythread.h"
77static long main_thread;
78static pid_t main_pid;
79#endif
80
81static struct {
82    int tripped;
83    PyObject *func;
84} Handlers[NSIG];
85
86static sig_atomic_t wakeup_fd = -1;
87
88/* Speed up sigcheck() when none tripped */
89static volatile sig_atomic_t is_tripped = 0;
90
91static PyObject *DefaultHandler;
92static PyObject *IgnoreHandler;
93static PyObject *IntHandler;
94
95/* On Solaris 8, gcc will produce a warning that the function
96   declaration is not a prototype. This is caused by the definition of
97   SIG_DFL as (void (*)())0; the correct declaration would have been
98   (void (*)(int))0. */
99
100static PyOS_sighandler_t old_siginthandler = SIG_DFL;
101
102#ifdef HAVE_GETITIMER
103static PyObject *ItimerError;
104
105/* auxiliary functions for setitimer/getitimer */
106static void
107timeval_from_double(double d, struct timeval *tv)
108{
109    tv->tv_sec = floor(d);
110    tv->tv_usec = fmod(d, 1.0) * 1000000.0;
111}
112
113Py_LOCAL_INLINE(double)
114double_from_timeval(struct timeval *tv)
115{
116    return tv->tv_sec + (double)(tv->tv_usec / 1000000.0);
117}
118
119static PyObject *
120itimer_retval(struct itimerval *iv)
121{
122    PyObject *r, *v;
123
124    r = PyTuple_New(2);
125    if (r == NULL)
126    return NULL;
127
128    if(!(v = PyFloat_FromDouble(double_from_timeval(&iv->it_value)))) {
129    Py_DECREF(r);
130    return NULL;
131    }
132
133    PyTuple_SET_ITEM(r, 0, v);
134
135    if(!(v = PyFloat_FromDouble(double_from_timeval(&iv->it_interval)))) {
136    Py_DECREF(r);
137    return NULL;
138    }
139
140    PyTuple_SET_ITEM(r, 1, v);
141
142    return r;
143}
144#endif
145
146static PyObject *
147signal_default_int_handler(PyObject *self, PyObject *args)
148{
149    PyErr_SetNone(PyExc_KeyboardInterrupt);
150    return NULL;
151}
152
153PyDoc_STRVAR(default_int_handler_doc,
154"default_int_handler(...)\n\
155\n\
156The default handler for SIGINT installed by Python.\n\
157It raises KeyboardInterrupt.");
158
159
160static int
161checksignals_witharg(void * unused)
162{
163    return PyErr_CheckSignals();
164}
165
166static void
167signal_handler(int sig_num)
168{
169#ifdef WITH_THREAD
170#ifdef WITH_PTH
171    if (PyThread_get_thread_ident() != main_thread) {
172        pth_raise(*(pth_t *) main_thread, sig_num);
173        return;
174    }
175#endif
176    /* See NOTES section above */
177    if (getpid() == main_pid) {
178#endif
179        Handlers[sig_num].tripped = 1;
180        /* Set is_tripped after setting .tripped, as it gets
181           cleared in PyErr_CheckSignals() before .tripped. */
182        is_tripped = 1;
183        Py_AddPendingCall(checksignals_witharg, NULL);
184        if (wakeup_fd != -1)
185            write(wakeup_fd, "\0", 1);
186#ifdef WITH_THREAD
187    }
188#endif
189#ifdef SIGCHLD
190    if (sig_num == SIGCHLD) {
191        /* To avoid infinite recursion, this signal remains
192           reset until explicit re-instated.
193           Don't clear the 'func' field as it is our pointer
194           to the Python handler... */
195        return;
196    }
197#endif
198#ifndef HAVE_SIGACTION
199    /* If the handler was not set up with sigaction, reinstall it.  See
200     * Python/pythonrun.c for the implementation of PyOS_setsig which
201     * makes this true.  See also issue8354. */
202    PyOS_setsig(sig_num, signal_handler);
203#endif
204}
205
206
207#ifdef HAVE_ALARM
208static PyObject *
209signal_alarm(PyObject *self, PyObject *args)
210{
211    int t;
212    if (!PyArg_ParseTuple(args, "i:alarm", &t))
213        return NULL;
214    /* alarm() returns the number of seconds remaining */
215    return PyLong_FromLong((long)alarm(t));
216}
217
218PyDoc_STRVAR(alarm_doc,
219"alarm(seconds)\n\
220\n\
221Arrange for SIGALRM to arrive after the given number of seconds.");
222#endif
223
224#ifdef HAVE_PAUSE
225static PyObject *
226signal_pause(PyObject *self)
227{
228    Py_BEGIN_ALLOW_THREADS
229    (void)pause();
230    Py_END_ALLOW_THREADS
231    /* make sure that any exceptions that got raised are propagated
232     * back into Python
233     */
234    if (PyErr_CheckSignals())
235        return NULL;
236
237    Py_INCREF(Py_None);
238    return Py_None;
239}
240PyDoc_STRVAR(pause_doc,
241"pause()\n\
242\n\
243Wait until a signal arrives.");
244
245#endif
246
247
248static PyObject *
249signal_signal(PyObject *self, PyObject *args)
250{
251    PyObject *obj;
252    int sig_num;
253    PyObject *old_handler;
254    void (*func)(int);
255#ifdef MS_WINDOWS
256    int cur_sig, num_valid_sigs = 6;
257    static int valid_sigs[] = {SIGABRT, SIGFPE, SIGILL, SIGINT,
258                               SIGSEGV, SIGTERM};
259    BOOL valid_sig = FALSE;
260#endif
261    if (!PyArg_ParseTuple(args, "iO:signal", &sig_num, &obj))
262        return NULL;
263#ifdef MS_WINDOWS
264    /* Validate that sig_num is one of the allowable signals */
265    for (cur_sig = 0; cur_sig < num_valid_sigs; cur_sig++)
266        valid_sig |= (sig_num == valid_sigs[cur_sig]);
267    if (!valid_sig) {
268        PyErr_SetString(PyExc_ValueError, "signal number out of range");
269        return NULL;
270    }
271#endif
272#ifdef WITH_THREAD
273    if (PyThread_get_thread_ident() != main_thread) {
274        PyErr_SetString(PyExc_ValueError,
275                        "signal only works in main thread");
276        return NULL;
277    }
278#endif
279    if (sig_num < 1 || sig_num >= NSIG) {
280        PyErr_SetString(PyExc_ValueError,
281                        "signal number out of range");
282        return NULL;
283    }
284    if (obj == IgnoreHandler)
285        func = SIG_IGN;
286    else if (obj == DefaultHandler)
287        func = SIG_DFL;
288    else if (!PyCallable_Check(obj)) {
289        PyErr_SetString(PyExc_TypeError,
290"signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
291                return NULL;
292    }
293    else
294        func = signal_handler;
295    if (PyOS_setsig(sig_num, func) == SIG_ERR) {
296        PyErr_SetFromErrno(PyExc_RuntimeError);
297        return NULL;
298    }
299    old_handler = Handlers[sig_num].func;
300    Handlers[sig_num].tripped = 0;
301    Py_INCREF(obj);
302    Handlers[sig_num].func = obj;
303    return old_handler;
304}
305
306PyDoc_STRVAR(signal_doc,
307"signal(sig, action) -> action\n\
308\n\
309Set the action for the given signal.  The action can be SIG_DFL,\n\
310SIG_IGN, or a callable Python object.  The previous action is\n\
311returned.  See getsignal() for possible return values.\n\
312\n\
313*** IMPORTANT NOTICE ***\n\
314A signal handler function is called with two arguments:\n\
315the first is the signal number, the second is the interrupted stack frame.");
316
317
318static PyObject *
319signal_getsignal(PyObject *self, PyObject *args)
320{
321    int sig_num;
322    PyObject *old_handler;
323    if (!PyArg_ParseTuple(args, "i:getsignal", &sig_num))
324        return NULL;
325    if (sig_num < 1 || sig_num >= NSIG) {
326        PyErr_SetString(PyExc_ValueError,
327                        "signal number out of range");
328        return NULL;
329    }
330    old_handler = Handlers[sig_num].func;
331    Py_INCREF(old_handler);
332    return old_handler;
333}
334
335PyDoc_STRVAR(getsignal_doc,
336"getsignal(sig) -> action\n\
337\n\
338Return the current action for the given signal.  The return value can be:\n\
339SIG_IGN -- if the signal is being ignored\n\
340SIG_DFL -- if the default action for the signal is in effect\n\
341None -- if an unknown handler is in effect\n\
342anything else -- the callable Python object used as a handler");
343
344#ifdef HAVE_SIGINTERRUPT
345PyDoc_STRVAR(siginterrupt_doc,
346"siginterrupt(sig, flag) -> None\n\
347change system call restart behaviour: if flag is False, system calls\n\
348will be restarted when interrupted by signal sig, else system calls\n\
349will be interrupted.");
350
351static PyObject *
352signal_siginterrupt(PyObject *self, PyObject *args)
353{
354    int sig_num;
355    int flag;
356
357    if (!PyArg_ParseTuple(args, "ii:siginterrupt", &sig_num, &flag))
358        return NULL;
359    if (sig_num < 1 || sig_num >= NSIG) {
360        PyErr_SetString(PyExc_ValueError,
361                        "signal number out of range");
362        return NULL;
363    }
364    if (siginterrupt(sig_num, flag)<0) {
365        PyErr_SetFromErrno(PyExc_RuntimeError);
366        return NULL;
367    }
368
369    Py_INCREF(Py_None);
370    return Py_None;
371}
372
373#endif
374
375static PyObject *
376signal_set_wakeup_fd(PyObject *self, PyObject *args)
377{
378    struct stat buf;
379    int fd, old_fd;
380    if (!PyArg_ParseTuple(args, "i:set_wakeup_fd", &fd))
381        return NULL;
382#ifdef WITH_THREAD
383    if (PyThread_get_thread_ident() != main_thread) {
384        PyErr_SetString(PyExc_ValueError,
385                        "set_wakeup_fd only works in main thread");
386        return NULL;
387    }
388#endif
389    if (fd != -1 && fstat(fd, &buf) != 0) {
390        PyErr_SetString(PyExc_ValueError, "invalid fd");
391        return NULL;
392    }
393    old_fd = wakeup_fd;
394    wakeup_fd = fd;
395    return PyLong_FromLong(old_fd);
396}
397
398PyDoc_STRVAR(set_wakeup_fd_doc,
399"set_wakeup_fd(fd) -> fd\n\
400\n\
401Sets the fd to be written to (with '\\0') when a signal\n\
402comes in.  A library can use this to wakeup select or poll.\n\
403The previous fd is returned.\n\
404\n\
405The fd must be non-blocking.");
406
407/* C API for the same, without all the error checking */
408int
409PySignal_SetWakeupFd(int fd)
410{
411    int old_fd = wakeup_fd;
412    if (fd < 0)
413        fd = -1;
414    wakeup_fd = fd;
415    return old_fd;
416}
417
418
419#ifdef HAVE_SETITIMER
420static PyObject *
421signal_setitimer(PyObject *self, PyObject *args)
422{
423    double first;
424    double interval = 0;
425    int which;
426    struct itimerval new, old;
427
428    if(!PyArg_ParseTuple(args, "id|d:setitimer", &which, &first, &interval))
429    return NULL;
430
431    timeval_from_double(first, &new.it_value);
432    timeval_from_double(interval, &new.it_interval);
433    /* Let OS check "which" value */
434    if (setitimer(which, &new, &old) != 0) {
435    PyErr_SetFromErrno(ItimerError);
436    return NULL;
437    }
438
439    return itimer_retval(&old);
440}
441
442PyDoc_STRVAR(setitimer_doc,
443"setitimer(which, seconds[, interval])\n\
444\n\
445Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL\n\
446or ITIMER_PROF) to fire after value seconds and after\n\
447that every interval seconds.\n\
448The itimer can be cleared by setting seconds to zero.\n\
449\n\
450Returns old values as a tuple: (delay, interval).");
451#endif
452
453
454#ifdef HAVE_GETITIMER
455static PyObject *
456signal_getitimer(PyObject *self, PyObject *args)
457{
458    int which;
459    struct itimerval old;
460
461    if (!PyArg_ParseTuple(args, "i:getitimer", &which))
462    return NULL;
463
464    if (getitimer(which, &old) != 0) {
465    PyErr_SetFromErrno(ItimerError);
466    return NULL;
467    }
468
469    return itimer_retval(&old);
470}
471
472PyDoc_STRVAR(getitimer_doc,
473"getitimer(which)\n\
474\n\
475Returns current value of given itimer.");
476#endif
477
478
479/* List of functions defined in the module */
480static PyMethodDef signal_methods[] = {
481#ifdef HAVE_ALARM
482    {"alarm",                   signal_alarm, METH_VARARGS, alarm_doc},
483#endif
484#ifdef HAVE_SETITIMER
485    {"setitimer",       signal_setitimer, METH_VARARGS, setitimer_doc},
486#endif
487#ifdef HAVE_GETITIMER
488    {"getitimer",       signal_getitimer, METH_VARARGS, getitimer_doc},
489#endif
490    {"signal",                  signal_signal, METH_VARARGS, signal_doc},
491    {"getsignal",               signal_getsignal, METH_VARARGS, getsignal_doc},
492    {"set_wakeup_fd",           signal_set_wakeup_fd, METH_VARARGS, set_wakeup_fd_doc},
493#ifdef HAVE_SIGINTERRUPT
494    {"siginterrupt",            signal_siginterrupt, METH_VARARGS, siginterrupt_doc},
495#endif
496#ifdef HAVE_PAUSE
497    {"pause",                   (PyCFunction)signal_pause,
498     METH_NOARGS,pause_doc},
499#endif
500    {"default_int_handler", signal_default_int_handler,
501     METH_VARARGS, default_int_handler_doc},
502    {NULL,                      NULL}           /* sentinel */
503};
504
505
506PyDoc_STRVAR(module_doc,
507"This module provides mechanisms to use signal handlers in Python.\n\
508\n\
509Functions:\n\
510\n\
511alarm() -- cause SIGALRM after a specified time [Unix only]\n\
512setitimer() -- cause a signal (described below) after a specified\n\
513               float time and the timer may restart then [Unix only]\n\
514getitimer() -- get current value of timer [Unix only]\n\
515signal() -- set the action for a given signal\n\
516getsignal() -- get the signal action for a given signal\n\
517pause() -- wait until a signal arrives [Unix only]\n\
518default_int_handler() -- default SIGINT handler\n\
519\n\
520signal constants:\n\
521SIG_DFL -- used to refer to the system default handler\n\
522SIG_IGN -- used to ignore the signal\n\
523NSIG -- number of defined signals\n\
524SIGINT, SIGTERM, etc. -- signal numbers\n\
525\n\
526itimer constants:\n\
527ITIMER_REAL -- decrements in real time, and delivers SIGALRM upon\n\
528               expiration\n\
529ITIMER_VIRTUAL -- decrements only when the process is executing,\n\
530               and delivers SIGVTALRM upon expiration\n\
531ITIMER_PROF -- decrements both when the process is executing and\n\
532               when the system is executing on behalf of the process.\n\
533               Coupled with ITIMER_VIRTUAL, this timer is usually\n\
534               used to profile the time spent by the application\n\
535               in user and kernel space. SIGPROF is delivered upon\n\
536               expiration.\n\
537\n\n\
538*** IMPORTANT NOTICE ***\n\
539A signal handler function is called with two arguments:\n\
540the first is the signal number, the second is the interrupted stack frame.");
541
542static struct PyModuleDef signalmodule = {
543    PyModuleDef_HEAD_INIT,
544    "signal",
545    module_doc,
546    -1,
547    signal_methods,
548    NULL,
549    NULL,
550    NULL,
551    NULL
552};
553
554PyMODINIT_FUNC
555PyInit_signal(void)
556{
557    PyObject *m, *d, *x;
558    int i;
559
560#ifdef WITH_THREAD
561    main_thread = PyThread_get_thread_ident();
562    main_pid = getpid();
563#endif
564
565    /* Create the module and add the functions */
566    m = PyModule_Create(&signalmodule);
567    if (m == NULL)
568        return NULL;
569
570    /* Add some symbolic constants to the module */
571    d = PyModule_GetDict(m);
572
573    x = DefaultHandler = PyLong_FromVoidPtr((void *)SIG_DFL);
574    if (!x || PyDict_SetItemString(d, "SIG_DFL", x) < 0)
575        goto finally;
576
577    x = IgnoreHandler = PyLong_FromVoidPtr((void *)SIG_IGN);
578    if (!x || PyDict_SetItemString(d, "SIG_IGN", x) < 0)
579        goto finally;
580
581    x = PyLong_FromLong((long)NSIG);
582    if (!x || PyDict_SetItemString(d, "NSIG", x) < 0)
583        goto finally;
584    Py_DECREF(x);
585
586    x = IntHandler = PyDict_GetItemString(d, "default_int_handler");
587    if (!x)
588        goto finally;
589    Py_INCREF(IntHandler);
590
591    Handlers[0].tripped = 0;
592    for (i = 1; i < NSIG; i++) {
593        void (*t)(int);
594        t = PyOS_getsig(i);
595        Handlers[i].tripped = 0;
596        if (t == SIG_DFL)
597            Handlers[i].func = DefaultHandler;
598        else if (t == SIG_IGN)
599            Handlers[i].func = IgnoreHandler;
600        else
601            Handlers[i].func = Py_None; /* None of our business */
602        Py_INCREF(Handlers[i].func);
603    }
604    if (Handlers[SIGINT].func == DefaultHandler) {
605        /* Install default int handler */
606        Py_INCREF(IntHandler);
607        Py_DECREF(Handlers[SIGINT].func);
608        Handlers[SIGINT].func = IntHandler;
609        old_siginthandler = PyOS_setsig(SIGINT, signal_handler);
610    }
611
612#ifdef SIGHUP
613    x = PyLong_FromLong(SIGHUP);
614    PyDict_SetItemString(d, "SIGHUP", x);
615    Py_XDECREF(x);
616#endif
617#ifdef SIGINT
618    x = PyLong_FromLong(SIGINT);
619    PyDict_SetItemString(d, "SIGINT", x);
620    Py_XDECREF(x);
621#endif
622#ifdef SIGBREAK
623    x = PyLong_FromLong(SIGBREAK);
624    PyDict_SetItemString(d, "SIGBREAK", x);
625    Py_XDECREF(x);
626#endif
627#ifdef SIGQUIT
628    x = PyLong_FromLong(SIGQUIT);
629    PyDict_SetItemString(d, "SIGQUIT", x);
630    Py_XDECREF(x);
631#endif
632#ifdef SIGILL
633    x = PyLong_FromLong(SIGILL);
634    PyDict_SetItemString(d, "SIGILL", x);
635    Py_XDECREF(x);
636#endif
637#ifdef SIGTRAP
638    x = PyLong_FromLong(SIGTRAP);
639    PyDict_SetItemString(d, "SIGTRAP", x);
640    Py_XDECREF(x);
641#endif
642#ifdef SIGIOT
643    x = PyLong_FromLong(SIGIOT);
644    PyDict_SetItemString(d, "SIGIOT", x);
645    Py_XDECREF(x);
646#endif
647#ifdef SIGABRT
648    x = PyLong_FromLong(SIGABRT);
649    PyDict_SetItemString(d, "SIGABRT", x);
650    Py_XDECREF(x);
651#endif
652#ifdef SIGEMT
653    x = PyLong_FromLong(SIGEMT);
654    PyDict_SetItemString(d, "SIGEMT", x);
655    Py_XDECREF(x);
656#endif
657#ifdef SIGFPE
658    x = PyLong_FromLong(SIGFPE);
659    PyDict_SetItemString(d, "SIGFPE", x);
660    Py_XDECREF(x);
661#endif
662#ifdef SIGKILL
663    x = PyLong_FromLong(SIGKILL);
664    PyDict_SetItemString(d, "SIGKILL", x);
665    Py_XDECREF(x);
666#endif
667#ifdef SIGBUS
668    x = PyLong_FromLong(SIGBUS);
669    PyDict_SetItemString(d, "SIGBUS", x);
670    Py_XDECREF(x);
671#endif
672#ifdef SIGSEGV
673    x = PyLong_FromLong(SIGSEGV);
674    PyDict_SetItemString(d, "SIGSEGV", x);
675    Py_XDECREF(x);
676#endif
677#ifdef SIGSYS
678    x = PyLong_FromLong(SIGSYS);
679    PyDict_SetItemString(d, "SIGSYS", x);
680    Py_XDECREF(x);
681#endif
682#ifdef SIGPIPE
683    x = PyLong_FromLong(SIGPIPE);
684    PyDict_SetItemString(d, "SIGPIPE", x);
685    Py_XDECREF(x);
686#endif
687#ifdef SIGALRM
688    x = PyLong_FromLong(SIGALRM);
689    PyDict_SetItemString(d, "SIGALRM", x);
690    Py_XDECREF(x);
691#endif
692#ifdef SIGTERM
693    x = PyLong_FromLong(SIGTERM);
694    PyDict_SetItemString(d, "SIGTERM", x);
695    Py_XDECREF(x);
696#endif
697#ifdef SIGUSR1
698    x = PyLong_FromLong(SIGUSR1);
699    PyDict_SetItemString(d, "SIGUSR1", x);
700    Py_XDECREF(x);
701#endif
702#ifdef SIGUSR2
703    x = PyLong_FromLong(SIGUSR2);
704    PyDict_SetItemString(d, "SIGUSR2", x);
705    Py_XDECREF(x);
706#endif
707#ifdef SIGCLD
708    x = PyLong_FromLong(SIGCLD);
709    PyDict_SetItemString(d, "SIGCLD", x);
710    Py_XDECREF(x);
711#endif
712#ifdef SIGCHLD
713    x = PyLong_FromLong(SIGCHLD);
714    PyDict_SetItemString(d, "SIGCHLD", x);
715    Py_XDECREF(x);
716#endif
717#ifdef SIGPWR
718    x = PyLong_FromLong(SIGPWR);
719    PyDict_SetItemString(d, "SIGPWR", x);
720    Py_XDECREF(x);
721#endif
722#ifdef SIGIO
723    x = PyLong_FromLong(SIGIO);
724    PyDict_SetItemString(d, "SIGIO", x);
725    Py_XDECREF(x);
726#endif
727#ifdef SIGURG
728    x = PyLong_FromLong(SIGURG);
729    PyDict_SetItemString(d, "SIGURG", x);
730    Py_XDECREF(x);
731#endif
732#ifdef SIGWINCH
733    x = PyLong_FromLong(SIGWINCH);
734    PyDict_SetItemString(d, "SIGWINCH", x);
735    Py_XDECREF(x);
736#endif
737#ifdef SIGPOLL
738    x = PyLong_FromLong(SIGPOLL);
739    PyDict_SetItemString(d, "SIGPOLL", x);
740    Py_XDECREF(x);
741#endif
742#ifdef SIGSTOP
743    x = PyLong_FromLong(SIGSTOP);
744    PyDict_SetItemString(d, "SIGSTOP", x);
745    Py_XDECREF(x);
746#endif
747#ifdef SIGTSTP
748    x = PyLong_FromLong(SIGTSTP);
749    PyDict_SetItemString(d, "SIGTSTP", x);
750    Py_XDECREF(x);
751#endif
752#ifdef SIGCONT
753    x = PyLong_FromLong(SIGCONT);
754    PyDict_SetItemString(d, "SIGCONT", x);
755    Py_XDECREF(x);
756#endif
757#ifdef SIGTTIN
758    x = PyLong_FromLong(SIGTTIN);
759    PyDict_SetItemString(d, "SIGTTIN", x);
760    Py_XDECREF(x);
761#endif
762#ifdef SIGTTOU
763    x = PyLong_FromLong(SIGTTOU);
764    PyDict_SetItemString(d, "SIGTTOU", x);
765    Py_XDECREF(x);
766#endif
767#ifdef SIGVTALRM
768    x = PyLong_FromLong(SIGVTALRM);
769    PyDict_SetItemString(d, "SIGVTALRM", x);
770    Py_XDECREF(x);
771#endif
772#ifdef SIGPROF
773    x = PyLong_FromLong(SIGPROF);
774    PyDict_SetItemString(d, "SIGPROF", x);
775    Py_XDECREF(x);
776#endif
777#ifdef SIGXCPU
778    x = PyLong_FromLong(SIGXCPU);
779    PyDict_SetItemString(d, "SIGXCPU", x);
780    Py_XDECREF(x);
781#endif
782#ifdef SIGXFSZ
783    x = PyLong_FromLong(SIGXFSZ);
784    PyDict_SetItemString(d, "SIGXFSZ", x);
785    Py_XDECREF(x);
786#endif
787#ifdef SIGRTMIN
788    x = PyLong_FromLong(SIGRTMIN);
789    PyDict_SetItemString(d, "SIGRTMIN", x);
790    Py_XDECREF(x);
791#endif
792#ifdef SIGRTMAX
793    x = PyLong_FromLong(SIGRTMAX);
794    PyDict_SetItemString(d, "SIGRTMAX", x);
795    Py_XDECREF(x);
796#endif
797#ifdef SIGINFO
798    x = PyLong_FromLong(SIGINFO);
799    PyDict_SetItemString(d, "SIGINFO", x);
800    Py_XDECREF(x);
801#endif
802
803#ifdef ITIMER_REAL
804    x = PyLong_FromLong(ITIMER_REAL);
805    PyDict_SetItemString(d, "ITIMER_REAL", x);
806    Py_DECREF(x);
807#endif
808#ifdef ITIMER_VIRTUAL
809    x = PyLong_FromLong(ITIMER_VIRTUAL);
810    PyDict_SetItemString(d, "ITIMER_VIRTUAL", x);
811    Py_DECREF(x);
812#endif
813#ifdef ITIMER_PROF
814    x = PyLong_FromLong(ITIMER_PROF);
815    PyDict_SetItemString(d, "ITIMER_PROF", x);
816    Py_DECREF(x);
817#endif
818
819#if defined (HAVE_SETITIMER) || defined (HAVE_GETITIMER)
820    ItimerError = PyErr_NewException("signal.ItimerError",
821     PyExc_IOError, NULL);
822    if (ItimerError != NULL)
823    PyDict_SetItemString(d, "ItimerError", ItimerError);
824#endif
825
826    if (PyErr_Occurred()) {
827        Py_DECREF(m);
828        m = NULL;
829    }
830
831  finally:
832    return m;
833}
834
835static void
836finisignal(void)
837{
838    int i;
839    PyObject *func;
840
841    PyOS_setsig(SIGINT, old_siginthandler);
842    old_siginthandler = SIG_DFL;
843
844    for (i = 1; i < NSIG; i++) {
845        func = Handlers[i].func;
846        Handlers[i].tripped = 0;
847        Handlers[i].func = NULL;
848        if (i != SIGINT && func != NULL && func != Py_None &&
849            func != DefaultHandler && func != IgnoreHandler)
850            PyOS_setsig(i, SIG_DFL);
851        Py_XDECREF(func);
852    }
853
854    Py_XDECREF(IntHandler);
855    IntHandler = NULL;
856    Py_XDECREF(DefaultHandler);
857    DefaultHandler = NULL;
858    Py_XDECREF(IgnoreHandler);
859    IgnoreHandler = NULL;
860}
861
862
863/* Declared in pyerrors.h */
864int
865PyErr_CheckSignals(void)
866{
867    int i;
868    PyObject *f;
869
870    if (!is_tripped)
871        return 0;
872
873#ifdef WITH_THREAD
874    if (PyThread_get_thread_ident() != main_thread)
875        return 0;
876#endif
877
878    /*
879     * The is_tripped variable is meant to speed up the calls to
880     * PyErr_CheckSignals (both directly or via pending calls) when no
881     * signal has arrived. This variable is set to 1 when a signal arrives
882     * and it is set to 0 here, when we know some signals arrived. This way
883     * we can run the registered handlers with no signals blocked.
884     *
885     * NOTE: with this approach we can have a situation where is_tripped is
886     *       1 but we have no more signals to handle (Handlers[i].tripped
887     *       is 0 for every signal i). This won't do us any harm (except
888     *       we're gonna spent some cycles for nothing). This happens when
889     *       we receive a signal i after we zero is_tripped and before we
890     *       check Handlers[i].tripped.
891     */
892    is_tripped = 0;
893
894    if (!(f = (PyObject *)PyEval_GetFrame()))
895        f = Py_None;
896
897    for (i = 1; i < NSIG; i++) {
898        if (Handlers[i].tripped) {
899            PyObject *result = NULL;
900            PyObject *arglist = Py_BuildValue("(iO)", i, f);
901            Handlers[i].tripped = 0;
902
903            if (arglist) {
904                result = PyEval_CallObject(Handlers[i].func,
905                                           arglist);
906                Py_DECREF(arglist);
907            }
908            if (!result)
909                return -1;
910
911            Py_DECREF(result);
912        }
913    }
914
915    return 0;
916}
917
918
919/* Replacements for intrcheck.c functionality
920 * Declared in pyerrors.h
921 */
922void
923PyErr_SetInterrupt(void)
924{
925    is_tripped = 1;
926    Handlers[SIGINT].tripped = 1;
927    Py_AddPendingCall((int (*)(void *))PyErr_CheckSignals, NULL);
928}
929
930void
931PyOS_InitInterrupts(void)
932{
933    PyObject *m = PyInit_signal();
934    if (m) {
935        _PyImport_FixupExtension(m, "signal", "signal");
936        Py_DECREF(m);
937    }
938}
939
940void
941PyOS_FiniInterrupts(void)
942{
943    finisignal();
944}
945
946int
947PyOS_InterruptOccurred(void)
948{
949    if (Handlers[SIGINT].tripped) {
950#ifdef WITH_THREAD
951        if (PyThread_get_thread_ident() != main_thread)
952            return 0;
953#endif
954        Handlers[SIGINT].tripped = 0;
955        return 1;
956    }
957    return 0;
958}
959
960void
961PyOS_AfterFork(void)
962{
963#ifdef WITH_THREAD
964    PyEval_ReInitThreads();
965    main_thread = PyThread_get_thread_ident();
966    main_pid = getpid();
967    _PyImport_ReInitLock();
968    PyThread_ReInitTLS();
969#endif
970}
971