source: python/vendor/Python-2.6.5/Modules/signalmodule.c

Last change on this file was 2, checked in by Yuri Dario, 15 years ago

Initial import for vendor code.

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