signalmodule.c revision cc6a438d7f33749859653d12ab963b014b1458bd
1/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5                        All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
16
17While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
29
30******************************************************************/
31
32/* Signal module -- many thanks to Lance Ellinghaus */
33
34/* XXX Signals should be recorded per thread, now we have thread state. */
35
36#include "Python.h"
37#include "intrcheck.h"
38
39#ifdef MS_WIN32
40#include <process.h>
41#endif
42
43#ifdef HAVE_UNISTD_H
44#include <unistd.h>
45#endif
46
47#include <signal.h>
48
49#ifndef SIG_ERR
50#define SIG_ERR ((RETSIGTYPE (*)())-1)
51#endif
52
53#if defined(PYOS_OS2)
54#define NSIG 12
55#include <process.h>
56#endif
57
58#ifndef NSIG
59#ifdef _SIGMAX
60#define NSIG (_SIGMAX + 1)	/* For QNX */
61#else
62#define NSIG (SIGMAX + 1)	/* for djgpp */
63#endif
64#endif
65
66
67
68/*
69   NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS
70
71   When threads are supported, we want the following semantics:
72
73   - only the main thread can set a signal handler
74   - any thread can get a signal handler
75   - signals are only delivered to the main thread
76
77   I.e. we don't support "synchronous signals" like SIGFPE (catching
78   this doesn't make much sense in Python anyway) nor do we support
79   signals as a means of inter-thread communication, since not all
80   thread implementations support that (at least our thread library
81   doesn't).
82
83   We still have the problem that in some implementations signals
84   generated by the keyboard (e.g. SIGINT) are delivered to all
85   threads (e.g. SGI), while in others (e.g. Solaris) such signals are
86   delivered to one random thread (an intermediate possibility would
87   be to deliver it to the main thread -- POSIX?).  For now, we have
88   a working implementation that works in all three cases -- the
89   handler ignores signals if getpid() isn't the same as in the main
90   thread.  XXX This is a hack.
91
92*/
93
94#ifdef WITH_THREAD
95#include <sys/types.h> /* For pid_t */
96#include "pythread.h"
97static long main_thread;
98static pid_t main_pid;
99#endif
100
101static struct {
102        int tripped;
103        PyObject *func;
104} Handlers[NSIG];
105
106static int is_tripped = 0; /* Speed up sigcheck() when none tripped */
107
108static PyObject *DefaultHandler;
109static PyObject *IgnoreHandler;
110static PyObject *IntHandler;
111
112static RETSIGTYPE (*old_siginthandler)() = SIG_DFL;
113
114
115
116static PyObject *
117signal_default_int_handler(self, arg)
118	PyObject *self;
119	PyObject *arg;
120{
121	PyErr_SetNone(PyExc_KeyboardInterrupt);
122	return NULL;
123}
124
125static char default_int_handler_doc[] =
126"default_int_handler(...)\n\
127\n\
128The default handler for SIGINT instated by Python.\n\
129It raises KeyboardInterrupt.";
130
131
132static RETSIGTYPE
133signal_handler(sig_num)
134	int sig_num;
135{
136#ifdef WITH_THREAD
137	/* See NOTES section above */
138	if (getpid() == main_pid) {
139#endif
140		is_tripped++;
141		Handlers[sig_num].tripped = 1;
142		Py_AddPendingCall(
143			(int (*) Py_PROTO((ANY *)))PyErr_CheckSignals, NULL);
144#ifdef WITH_THREAD
145	}
146#endif
147#ifdef SIGCHLD
148	if (sig_num == SIGCHLD) {
149		/* To avoid infinite recursion, this signal remains
150		   reset until explicit re-instated.
151		   Don't clear the 'func' field as it is our pointer
152		   to the Python handler... */
153		return;
154	}
155#endif
156#ifdef HAVE_SIGINTERRUPT
157	siginterrupt(sig_num, 1);
158#endif
159	(void)signal(sig_num, &signal_handler);
160}
161
162
163
164#ifdef HAVE_ALARM
165static PyObject *
166signal_alarm(self, args)
167	PyObject *self; /* Not used */
168	PyObject *args;
169{
170	int t;
171	if (!PyArg_Parse(args, "i", &t))
172		return NULL;
173	/* alarm() returns the number of seconds remaining */
174	return PyInt_FromLong(alarm(t));
175}
176
177static char alarm_doc[] =
178"alarm(seconds)\n\
179\n\
180Arrange for SIGALRM to arrive after the given number of seconds.";
181#endif
182
183#ifdef HAVE_PAUSE
184static PyObject *
185signal_pause(self, args)
186	PyObject *self; /* Not used */
187	PyObject *args;
188{
189	if (!PyArg_NoArgs(args))
190		return NULL;
191
192	Py_BEGIN_ALLOW_THREADS
193	(void)pause();
194	Py_END_ALLOW_THREADS
195	/* make sure that any exceptions that got raised are propagated
196	 * back into Python
197	 */
198	if (PyErr_CheckSignals())
199		return NULL;
200
201	Py_INCREF(Py_None);
202	return Py_None;
203}
204static char pause_doc[] =
205"pause()\n\
206\n\
207Wait until a signal arrives.";
208
209#endif
210
211
212static PyObject *
213signal_signal(self, args)
214	PyObject *self; /* Not used */
215	PyObject *args;
216{
217	PyObject *obj;
218	int sig_num;
219	PyObject *old_handler;
220	RETSIGTYPE (*func)();
221	if (!PyArg_Parse(args, "(iO)", &sig_num, &obj))
222		return NULL;
223#ifdef WITH_THREAD
224	if (PyThread_get_thread_ident() != main_thread) {
225		PyErr_SetString(PyExc_ValueError,
226				"signal only works in main thread");
227		return NULL;
228	}
229#endif
230	if (sig_num < 1 || sig_num >= NSIG) {
231		PyErr_SetString(PyExc_ValueError,
232				"signal number out of range");
233		return NULL;
234	}
235	if (obj == IgnoreHandler)
236		func = SIG_IGN;
237	else if (obj == DefaultHandler)
238		func = SIG_DFL;
239	else if (!PyCallable_Check(obj)) {
240		PyErr_SetString(PyExc_TypeError,
241"signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
242		return NULL;
243	}
244	else
245		func = signal_handler;
246#ifdef HAVE_SIGINTERRUPT
247	siginterrupt(sig_num, 1);
248#endif
249	if (signal(sig_num, func) == SIG_ERR) {
250		PyErr_SetFromErrno(PyExc_RuntimeError);
251		return NULL;
252	}
253	old_handler = Handlers[sig_num].func;
254	Handlers[sig_num].tripped = 0;
255	Py_INCREF(obj);
256	Handlers[sig_num].func = obj;
257	return old_handler;
258}
259
260static char signal_doc[] =
261"signal(sig, action) -> action\n\
262\n\
263Set the action for the given signal.  The action can be SIG_DFL,\n\
264SIG_IGN, or a callable Python object.  The previous action is\n\
265returned.  See getsignal() for possible return values.\n\
266\n\
267*** IMPORTANT NOTICE ***\n\
268A signal handler function is called with two arguments:\n\
269the first is the signal number, the second is the interrupted stack frame.";
270
271
272static PyObject *
273signal_getsignal(self, args)
274	PyObject *self; /* Not used */
275	PyObject *args;
276{
277	int sig_num;
278	PyObject *old_handler;
279	if (!PyArg_Parse(args, "i", &sig_num))
280		return NULL;
281	if (sig_num < 1 || sig_num >= NSIG) {
282		PyErr_SetString(PyExc_ValueError,
283				"signal number out of range");
284		return NULL;
285	}
286	old_handler = Handlers[sig_num].func;
287	Py_INCREF(old_handler);
288	return old_handler;
289}
290
291static char getsignal_doc[] =
292"getsignal(sig) -> action\n\
293\n\
294Return the current action for the given signal.  The return value can be:\n\
295SIG_IGN -- if the signal is being ignored\n\
296SIG_DFL -- if the default action for the signal is in effect\n\
297None -- if an unknown handler is in effect\n\
298anything else -- the callable Python object used as a handler\n\
299";
300
301
302/* List of functions defined in the module */
303static PyMethodDef signal_methods[] = {
304#ifdef HAVE_ALARM
305	{"alarm",	        signal_alarm, 0, alarm_doc},
306#endif
307	{"signal",	        signal_signal, 0, signal_doc},
308	{"getsignal",	        signal_getsignal, 0, getsignal_doc},
309#ifdef HAVE_PAUSE
310	{"pause",	        signal_pause, 0, pause_doc},
311#endif
312	{"default_int_handler", signal_default_int_handler, 0,
313				default_int_handler_doc},
314	{NULL,			NULL}		/* sentinel */
315};
316
317
318
319static char module_doc[] =
320"This module provides mechanisms to use signal handlers in Python.\n\
321\n\
322Functions:\n\
323\n\
324alarm() -- cause SIGALRM after a specified time [Unix only]\n\
325signal() -- set the action for a given signal\n\
326getsignal() -- get the signal action for a given signal\n\
327pause() -- wait until a signal arrives [Unix only]\n\
328default_int_handler() -- default SIGINT handler\n\
329\n\
330Constants:\n\
331\n\
332SIG_DFL -- used to refer to the system default handler\n\
333SIG_IGN -- used to ignore the signal\n\
334NSIG -- number of defined signals\n\
335\n\
336SIGINT, SIGTERM, etc. -- signal numbers\n\
337\n\
338*** IMPORTANT NOTICE ***\n\
339A signal handler function is called with two arguments:\n\
340the first is the signal number, the second is the interrupted stack frame.";
341
342DL_EXPORT(void)
343initsignal()
344{
345	PyObject *m, *d, *x;
346	int i;
347
348#ifdef WITH_THREAD
349	main_thread = PyThread_get_thread_ident();
350	main_pid = getpid();
351#endif
352
353	/* Create the module and add the functions */
354	m = Py_InitModule3("signal", signal_methods, module_doc);
355
356	/* Add some symbolic constants to the module */
357	d = PyModule_GetDict(m);
358
359	x = DefaultHandler = PyLong_FromVoidPtr(SIG_DFL);
360        if (!x || PyDict_SetItemString(d, "SIG_DFL", x) < 0)
361                goto finally;
362
363	x = IgnoreHandler = PyLong_FromVoidPtr(SIG_IGN);
364        if (!x || PyDict_SetItemString(d, "SIG_IGN", x) < 0)
365                goto finally;
366
367        x = PyInt_FromLong((long)NSIG);
368        if (!x || PyDict_SetItemString(d, "NSIG", x) < 0)
369                goto finally;
370        Py_DECREF(x);
371
372	x = IntHandler = PyDict_GetItemString(d, "default_int_handler");
373        if (!x)
374                goto finally;
375	Py_INCREF(IntHandler);
376
377	Handlers[0].tripped = 0;
378	for (i = 1; i < NSIG; i++) {
379		RETSIGTYPE (*t)();
380#ifdef HAVE_SIGACTION
381		struct sigaction act;
382		sigaction(i,  0, &act);
383		t = act.sa_handler;
384#else
385		t = signal(i, SIG_IGN);
386		signal(i, t);
387#endif
388		Handlers[i].tripped = 0;
389		if (t == SIG_DFL)
390			Handlers[i].func = DefaultHandler;
391		else if (t == SIG_IGN)
392			Handlers[i].func = IgnoreHandler;
393		else
394			Handlers[i].func = Py_None; /* None of our business */
395		Py_INCREF(Handlers[i].func);
396	}
397	if (Handlers[SIGINT].func == DefaultHandler) {
398		/* Install default int handler */
399		Py_INCREF(IntHandler);
400		Py_DECREF(Handlers[SIGINT].func);
401		Handlers[SIGINT].func = IntHandler;
402		old_siginthandler = signal(SIGINT, &signal_handler);
403	}
404
405#ifdef SIGHUP
406	x = PyInt_FromLong(SIGHUP);
407	PyDict_SetItemString(d, "SIGHUP", x);
408        Py_XDECREF(x);
409#endif
410#ifdef SIGINT
411	x = PyInt_FromLong(SIGINT);
412	PyDict_SetItemString(d, "SIGINT", x);
413        Py_XDECREF(x);
414#endif
415#ifdef SIGQUIT
416	x = PyInt_FromLong(SIGQUIT);
417	PyDict_SetItemString(d, "SIGQUIT", x);
418        Py_XDECREF(x);
419#endif
420#ifdef SIGILL
421	x = PyInt_FromLong(SIGILL);
422	PyDict_SetItemString(d, "SIGILL", x);
423        Py_XDECREF(x);
424#endif
425#ifdef SIGTRAP
426	x = PyInt_FromLong(SIGTRAP);
427	PyDict_SetItemString(d, "SIGTRAP", x);
428        Py_XDECREF(x);
429#endif
430#ifdef SIGIOT
431	x = PyInt_FromLong(SIGIOT);
432	PyDict_SetItemString(d, "SIGIOT", x);
433        Py_XDECREF(x);
434#endif
435#ifdef SIGABRT
436	x = PyInt_FromLong(SIGABRT);
437	PyDict_SetItemString(d, "SIGABRT", x);
438        Py_XDECREF(x);
439#endif
440#ifdef SIGEMT
441	x = PyInt_FromLong(SIGEMT);
442	PyDict_SetItemString(d, "SIGEMT", x);
443        Py_XDECREF(x);
444#endif
445#ifdef SIGFPE
446	x = PyInt_FromLong(SIGFPE);
447	PyDict_SetItemString(d, "SIGFPE", x);
448        Py_XDECREF(x);
449#endif
450#ifdef SIGKILL
451	x = PyInt_FromLong(SIGKILL);
452	PyDict_SetItemString(d, "SIGKILL", x);
453        Py_XDECREF(x);
454#endif
455#ifdef SIGBUS
456	x = PyInt_FromLong(SIGBUS);
457	PyDict_SetItemString(d, "SIGBUS", x);
458        Py_XDECREF(x);
459#endif
460#ifdef SIGSEGV
461	x = PyInt_FromLong(SIGSEGV);
462	PyDict_SetItemString(d, "SIGSEGV", x);
463        Py_XDECREF(x);
464#endif
465#ifdef SIGSYS
466	x = PyInt_FromLong(SIGSYS);
467	PyDict_SetItemString(d, "SIGSYS", x);
468        Py_XDECREF(x);
469#endif
470#ifdef SIGPIPE
471	x = PyInt_FromLong(SIGPIPE);
472	PyDict_SetItemString(d, "SIGPIPE", x);
473        Py_XDECREF(x);
474#endif
475#ifdef SIGALRM
476	x = PyInt_FromLong(SIGALRM);
477	PyDict_SetItemString(d, "SIGALRM", x);
478        Py_XDECREF(x);
479#endif
480#ifdef SIGTERM
481	x = PyInt_FromLong(SIGTERM);
482	PyDict_SetItemString(d, "SIGTERM", x);
483        Py_XDECREF(x);
484#endif
485#ifdef SIGUSR1
486	x = PyInt_FromLong(SIGUSR1);
487	PyDict_SetItemString(d, "SIGUSR1", x);
488        Py_XDECREF(x);
489#endif
490#ifdef SIGUSR2
491	x = PyInt_FromLong(SIGUSR2);
492	PyDict_SetItemString(d, "SIGUSR2", x);
493        Py_XDECREF(x);
494#endif
495#ifdef SIGCLD
496	x = PyInt_FromLong(SIGCLD);
497	PyDict_SetItemString(d, "SIGCLD", x);
498        Py_XDECREF(x);
499#endif
500#ifdef SIGCHLD
501	x = PyInt_FromLong(SIGCHLD);
502	PyDict_SetItemString(d, "SIGCHLD", x);
503        Py_XDECREF(x);
504#endif
505#ifdef SIGPWR
506	x = PyInt_FromLong(SIGPWR);
507	PyDict_SetItemString(d, "SIGPWR", x);
508        Py_XDECREF(x);
509#endif
510#ifdef SIGIO
511	x = PyInt_FromLong(SIGIO);
512	PyDict_SetItemString(d, "SIGIO", x);
513        Py_XDECREF(x);
514#endif
515#ifdef SIGURG
516	x = PyInt_FromLong(SIGURG);
517	PyDict_SetItemString(d, "SIGURG", x);
518        Py_XDECREF(x);
519#endif
520#ifdef SIGWINCH
521	x = PyInt_FromLong(SIGWINCH);
522	PyDict_SetItemString(d, "SIGWINCH", x);
523        Py_XDECREF(x);
524#endif
525#ifdef SIGPOLL
526	x = PyInt_FromLong(SIGPOLL);
527	PyDict_SetItemString(d, "SIGPOLL", x);
528        Py_XDECREF(x);
529#endif
530#ifdef SIGSTOP
531	x = PyInt_FromLong(SIGSTOP);
532	PyDict_SetItemString(d, "SIGSTOP", x);
533        Py_XDECREF(x);
534#endif
535#ifdef SIGTSTP
536	x = PyInt_FromLong(SIGTSTP);
537	PyDict_SetItemString(d, "SIGTSTP", x);
538        Py_XDECREF(x);
539#endif
540#ifdef SIGCONT
541	x = PyInt_FromLong(SIGCONT);
542	PyDict_SetItemString(d, "SIGCONT", x);
543        Py_XDECREF(x);
544#endif
545#ifdef SIGTTIN
546	x = PyInt_FromLong(SIGTTIN);
547	PyDict_SetItemString(d, "SIGTTIN", x);
548        Py_XDECREF(x);
549#endif
550#ifdef SIGTTOU
551	x = PyInt_FromLong(SIGTTOU);
552	PyDict_SetItemString(d, "SIGTTOU", x);
553        Py_XDECREF(x);
554#endif
555#ifdef SIGVTALRM
556	x = PyInt_FromLong(SIGVTALRM);
557	PyDict_SetItemString(d, "SIGVTALRM", x);
558        Py_XDECREF(x);
559#endif
560#ifdef SIGPROF
561	x = PyInt_FromLong(SIGPROF);
562	PyDict_SetItemString(d, "SIGPROF", x);
563        Py_XDECREF(x);
564#endif
565#ifdef SIGXCPU
566	x = PyInt_FromLong(SIGXCPU);
567	PyDict_SetItemString(d, "SIGXCPU", x);
568        Py_XDECREF(x);
569#endif
570#ifdef SIGXFSZ
571	x = PyInt_FromLong(SIGXFSZ);
572	PyDict_SetItemString(d, "SIGXFSZ", x);
573        Py_XDECREF(x);
574#endif
575        if (!PyErr_Occurred())
576                return;
577
578	/* Check for errors */
579  finally:
580        return;
581}
582
583static void
584finisignal()
585{
586	int i;
587	PyObject *func;
588
589	signal(SIGINT, old_siginthandler);
590	old_siginthandler = SIG_DFL;
591
592	for (i = 1; i < NSIG; i++) {
593		func = Handlers[i].func;
594		Handlers[i].tripped = 0;
595		Handlers[i].func = NULL;
596		if (i != SIGINT && func != NULL && func != Py_None &&
597		    func != DefaultHandler && func != IgnoreHandler)
598			signal(i, SIG_DFL);
599		Py_XDECREF(func);
600	}
601
602	Py_XDECREF(IntHandler);
603	IntHandler = NULL;
604	Py_XDECREF(DefaultHandler);
605	DefaultHandler = NULL;
606	Py_XDECREF(IgnoreHandler);
607	IgnoreHandler = NULL;
608}
609
610
611
612/* Declared in pyerrors.h */
613int
614PyErr_CheckSignals()
615{
616	int i;
617	PyObject *f;
618
619	if (!is_tripped)
620		return 0;
621#ifdef WITH_THREAD
622	if (PyThread_get_thread_ident() != main_thread)
623		return 0;
624#endif
625	if (!(f = PyEval_GetFrame()))
626		f = Py_None;
627
628	for (i = 1; i < NSIG; i++) {
629		if (Handlers[i].tripped) {
630			PyObject *result = NULL;
631			PyObject *arglist = Py_BuildValue("(iO)", i, f);
632			Handlers[i].tripped = 0;
633
634			if (arglist) {
635				result = PyEval_CallObject(Handlers[i].func,
636							   arglist);
637				Py_DECREF(arglist);
638			}
639			if (!result)
640				return -1;
641
642			Py_DECREF(result);
643		}
644	}
645	is_tripped = 0;
646	return 0;
647}
648
649
650/* Replacements for intrcheck.c functionality
651 * Declared in pyerrors.h
652 */
653void
654PyErr_SetInterrupt()
655{
656	is_tripped++;
657	Handlers[SIGINT].tripped = 1;
658	Py_AddPendingCall((int (*) Py_PROTO((ANY *)))PyErr_CheckSignals, NULL);
659}
660
661void
662PyOS_InitInterrupts()
663{
664	initsignal();
665	_PyImport_FixupExtension("signal", "signal");
666}
667
668void
669PyOS_FiniInterrupts()
670{
671	finisignal();
672}
673
674int
675PyOS_InterruptOccurred()
676{
677	if (Handlers[SIGINT].tripped) {
678#ifdef WITH_THREAD
679		if (PyThread_get_thread_ident() != main_thread)
680			return 0;
681#endif
682		Handlers[SIGINT].tripped = 0;
683		return 1;
684	}
685	return 0;
686}
687
688void
689PyOS_AfterFork()
690{
691#ifdef WITH_THREAD
692	main_thread = PyThread_get_thread_ident();
693	main_pid = getpid();
694#endif
695}
696