Improved some error messages for command line processing.
[python/dscho.git] / Modules / signalmodule.c
blob7ebad93efe64fca1e678fb8240a8fcf5bc59a325
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
15 permission.
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* Signal module -- many thanks to Lance Ellinghaus */
34 /* XXX Signals should be recorded per thread, now we have thread state. */
36 #include "Python.h"
37 #include "intrcheck.h"
39 #ifdef MS_WIN32
40 #include <process.h>
41 #endif
43 #ifdef HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
47 #include <signal.h>
49 #ifndef SIG_ERR
50 #define SIG_ERR ((RETSIGTYPE (*)())-1)
51 #endif
53 #if defined(PYOS_OS2)
54 #define NSIG 12
55 #include <process.h>
56 #endif
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
69 NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS
71 When threads are supported, we want the following semantics:
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
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).
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.
94 #ifdef WITH_THREAD
95 #include <sys/types.h> /* For pid_t */
96 #include "thread.h"
97 static long main_thread;
98 static pid_t main_pid;
99 #endif
101 static struct {
102 int tripped;
103 PyObject *func;
104 } Handlers[NSIG];
106 static int is_tripped = 0; /* Speed up sigcheck() when none tripped */
108 static PyObject *DefaultHandler;
109 static PyObject *IgnoreHandler;
110 static PyObject *IntHandler;
112 static RETSIGTYPE (*old_siginthandler)() = SIG_DFL;
116 static PyObject *
117 signal_default_int_handler(self, arg)
118 PyObject *self;
119 PyObject *arg;
121 PyErr_SetNone(PyExc_KeyboardInterrupt);
122 return NULL;
125 static char default_int_handler_doc[] =
126 "default_int_handler(...)\n\
128 The default handler for SIGINT instated by Python.\n\
129 It raises KeyboardInterrupt.";
132 static RETSIGTYPE
133 signal_handler(sig_num)
134 int sig_num;
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
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;
155 #endif
156 (void)signal(sig_num, &signal_handler);
161 #ifdef HAVE_ALARM
162 static PyObject *
163 signal_alarm(self, args)
164 PyObject *self; /* Not used */
165 PyObject *args;
167 int t;
168 if (!PyArg_Parse(args, "i", &t))
169 return NULL;
170 /* alarm() returns the number of seconds remaining */
171 return PyInt_FromLong(alarm(t));
174 static char alarm_doc[] =
175 "alarm(seconds)\n\
177 Arrange for SIGALRM to arrive after the given number of seconds.";
178 #endif
180 #ifdef HAVE_PAUSE
181 static PyObject *
182 signal_pause(self, args)
183 PyObject *self; /* Not used */
184 PyObject *args;
186 if (!PyArg_NoArgs(args))
187 return NULL;
189 Py_BEGIN_ALLOW_THREADS
190 (void)pause();
191 Py_END_ALLOW_THREADS
192 /* make sure that any exceptions that got raised are propagated
193 * back into Python
195 if (PyErr_CheckSignals())
196 return NULL;
198 Py_INCREF(Py_None);
199 return Py_None;
201 static char pause_doc[] =
202 "pause()\n\
204 Wait until a signal arrives.";
206 #endif
209 static PyObject *
210 signal_signal(self, args)
211 PyObject *self; /* Not used */
212 PyObject *args;
214 PyObject *obj;
215 int sig_num;
216 PyObject *old_handler;
217 RETSIGTYPE (*func)();
218 if (!PyArg_Parse(args, "(iO)", &sig_num, &obj))
219 return NULL;
220 #ifdef WITH_THREAD
221 if (get_thread_ident() != main_thread) {
222 PyErr_SetString(PyExc_ValueError,
223 "signal only works in main thread");
224 return NULL;
226 #endif
227 if (sig_num < 1 || sig_num >= NSIG) {
228 PyErr_SetString(PyExc_ValueError,
229 "signal number out of range");
230 return NULL;
232 if (obj == IgnoreHandler)
233 func = SIG_IGN;
234 else if (obj == DefaultHandler)
235 func = SIG_DFL;
236 else if (!PyCallable_Check(obj)) {
237 PyErr_SetString(PyExc_TypeError,
238 "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
239 return NULL;
241 else
242 func = signal_handler;
243 if (signal(sig_num, func) == SIG_ERR) {
244 PyErr_SetFromErrno(PyExc_RuntimeError);
245 return NULL;
247 old_handler = Handlers[sig_num].func;
248 Handlers[sig_num].tripped = 0;
249 Py_INCREF(obj);
250 Handlers[sig_num].func = obj;
251 return old_handler;
254 static char signal_doc[] =
255 "signal(sig, action) -> action\n\
257 Set the action for the given signal. The action can be SIG_DFL,\n\
258 SIG_IGN, or a callable Python object. The previous action is\n\
259 returned. See getsignal() for possible return values.\n\
261 *** IMPORTANT NOTICE ***\n\
262 A signal handler function is called with two arguments:\n\
263 the first is the signal number, the second is the interrupted stack frame.";
266 static PyObject *
267 signal_getsignal(self, args)
268 PyObject *self; /* Not used */
269 PyObject *args;
271 int sig_num;
272 PyObject *old_handler;
273 if (!PyArg_Parse(args, "i", &sig_num))
274 return NULL;
275 if (sig_num < 1 || sig_num >= NSIG) {
276 PyErr_SetString(PyExc_ValueError,
277 "signal number out of range");
278 return NULL;
280 old_handler = Handlers[sig_num].func;
281 Py_INCREF(old_handler);
282 return old_handler;
285 static char getsignal_doc[] =
286 "getsignal(sig) -> action\n\
288 Return the current action for the given signal. The return value can be:\n\
289 SIG_IGN -- if the signal is being ignored\n\
290 SIG_DFL -- if the default action for the signal is in effect\n\
291 None -- if an unknown handler is in effect\n\
292 anything else -- the callable Python object used as a handler\n\
296 /* List of functions defined in the module */
297 static PyMethodDef signal_methods[] = {
298 #ifdef HAVE_ALARM
299 {"alarm", signal_alarm, 0, alarm_doc},
300 #endif
301 {"signal", signal_signal, 0, signal_doc},
302 {"getsignal", signal_getsignal, 0, getsignal_doc},
303 #ifdef HAVE_PAUSE
304 {"pause", signal_pause, 0, pause_doc},
305 #endif
306 {"default_int_handler", signal_default_int_handler, 0,
307 default_int_handler_doc},
308 {NULL, NULL} /* sentinel */
313 static char module_doc[] =
314 "This module provides mechanisms to use signal handlers in Python.\n\
316 Functions:\n\
318 alarm() -- cause SIGALRM after a specified time [Unix only]\n\
319 signal() -- set the action for a given signal\n\
320 getsignal() -- get the signal action for a given signal\n\
321 pause() -- wait until a signal arrives [Unix only]\n\
322 default_int_handler() -- default SIGINT handler\n\
324 Constants:\n\
326 SIG_DFL -- used to refer to the system default handler\n\
327 SIG_IGN -- used to ignore the signal\n\
328 NSIG -- number of defined signals\n\
330 SIGINT, SIGTERM, etc. -- signal numbers\n\
332 *** IMPORTANT NOTICE ***\n\
333 A signal handler function is called with two arguments:\n\
334 the first is the signal number, the second is the interrupted stack frame.";
336 void
337 initsignal()
339 PyObject *m, *d, *x;
340 int i;
342 #ifdef WITH_THREAD
343 main_thread = get_thread_ident();
344 main_pid = getpid();
345 #endif
347 /* Create the module and add the functions */
348 m = Py_InitModule3("signal", signal_methods, module_doc);
350 /* Add some symbolic constants to the module */
351 d = PyModule_GetDict(m);
353 x = DefaultHandler = PyInt_FromLong((long)SIG_DFL);
354 if (!x || PyDict_SetItemString(d, "SIG_DFL", x) < 0)
355 goto finally;
357 x = IgnoreHandler = PyInt_FromLong((long)SIG_IGN);
358 if (!x || PyDict_SetItemString(d, "SIG_IGN", x) < 0)
359 goto finally;
361 x = PyInt_FromLong((long)NSIG);
362 if (!x || PyDict_SetItemString(d, "NSIG", x) < 0)
363 goto finally;
364 Py_DECREF(x);
366 x = IntHandler = PyDict_GetItemString(d, "default_int_handler");
367 if (!x)
368 goto finally;
369 Py_INCREF(IntHandler);
371 Handlers[0].tripped = 0;
372 for (i = 1; i < NSIG; i++) {
373 RETSIGTYPE (*t)();
374 #ifdef HAVE_SIGACTION
375 struct sigaction act;
376 sigaction(i, 0, &act);
377 t = act.sa_handler;
378 #else
379 t = signal(i, SIG_IGN);
380 signal(i, t);
381 #endif
382 Handlers[i].tripped = 0;
383 if (t == SIG_DFL)
384 Handlers[i].func = DefaultHandler;
385 else if (t == SIG_IGN)
386 Handlers[i].func = IgnoreHandler;
387 else
388 Handlers[i].func = Py_None; /* None of our business */
389 Py_INCREF(Handlers[i].func);
391 if (Handlers[SIGINT].func == DefaultHandler) {
392 /* Install default int handler */
393 Py_INCREF(IntHandler);
394 Py_DECREF(Handlers[SIGINT].func);
395 Handlers[SIGINT].func = IntHandler;
396 old_siginthandler = signal(SIGINT, &signal_handler);
399 #ifdef SIGHUP
400 x = PyInt_FromLong(SIGHUP);
401 PyDict_SetItemString(d, "SIGHUP", x);
402 Py_XDECREF(x);
403 #endif
404 #ifdef SIGINT
405 x = PyInt_FromLong(SIGINT);
406 PyDict_SetItemString(d, "SIGINT", x);
407 Py_XDECREF(x);
408 #endif
409 #ifdef SIGQUIT
410 x = PyInt_FromLong(SIGQUIT);
411 PyDict_SetItemString(d, "SIGQUIT", x);
412 Py_XDECREF(x);
413 #endif
414 #ifdef SIGILL
415 x = PyInt_FromLong(SIGILL);
416 PyDict_SetItemString(d, "SIGILL", x);
417 Py_XDECREF(x);
418 #endif
419 #ifdef SIGTRAP
420 x = PyInt_FromLong(SIGTRAP);
421 PyDict_SetItemString(d, "SIGTRAP", x);
422 Py_XDECREF(x);
423 #endif
424 #ifdef SIGIOT
425 x = PyInt_FromLong(SIGIOT);
426 PyDict_SetItemString(d, "SIGIOT", x);
427 Py_XDECREF(x);
428 #endif
429 #ifdef SIGABRT
430 x = PyInt_FromLong(SIGABRT);
431 PyDict_SetItemString(d, "SIGABRT", x);
432 Py_XDECREF(x);
433 #endif
434 #ifdef SIGEMT
435 x = PyInt_FromLong(SIGEMT);
436 PyDict_SetItemString(d, "SIGEMT", x);
437 Py_XDECREF(x);
438 #endif
439 #ifdef SIGFPE
440 x = PyInt_FromLong(SIGFPE);
441 PyDict_SetItemString(d, "SIGFPE", x);
442 Py_XDECREF(x);
443 #endif
444 #ifdef SIGKILL
445 x = PyInt_FromLong(SIGKILL);
446 PyDict_SetItemString(d, "SIGKILL", x);
447 Py_XDECREF(x);
448 #endif
449 #ifdef SIGBUS
450 x = PyInt_FromLong(SIGBUS);
451 PyDict_SetItemString(d, "SIGBUS", x);
452 Py_XDECREF(x);
453 #endif
454 #ifdef SIGSEGV
455 x = PyInt_FromLong(SIGSEGV);
456 PyDict_SetItemString(d, "SIGSEGV", x);
457 Py_XDECREF(x);
458 #endif
459 #ifdef SIGSYS
460 x = PyInt_FromLong(SIGSYS);
461 PyDict_SetItemString(d, "SIGSYS", x);
462 Py_XDECREF(x);
463 #endif
464 #ifdef SIGPIPE
465 x = PyInt_FromLong(SIGPIPE);
466 PyDict_SetItemString(d, "SIGPIPE", x);
467 Py_XDECREF(x);
468 #endif
469 #ifdef SIGALRM
470 x = PyInt_FromLong(SIGALRM);
471 PyDict_SetItemString(d, "SIGALRM", x);
472 Py_XDECREF(x);
473 #endif
474 #ifdef SIGTERM
475 x = PyInt_FromLong(SIGTERM);
476 PyDict_SetItemString(d, "SIGTERM", x);
477 Py_XDECREF(x);
478 #endif
479 #ifdef SIGUSR1
480 x = PyInt_FromLong(SIGUSR1);
481 PyDict_SetItemString(d, "SIGUSR1", x);
482 Py_XDECREF(x);
483 #endif
484 #ifdef SIGUSR2
485 x = PyInt_FromLong(SIGUSR2);
486 PyDict_SetItemString(d, "SIGUSR2", x);
487 Py_XDECREF(x);
488 #endif
489 #ifdef SIGCLD
490 x = PyInt_FromLong(SIGCLD);
491 PyDict_SetItemString(d, "SIGCLD", x);
492 Py_XDECREF(x);
493 #endif
494 #ifdef SIGCHLD
495 x = PyInt_FromLong(SIGCHLD);
496 PyDict_SetItemString(d, "SIGCHLD", x);
497 Py_XDECREF(x);
498 #endif
499 #ifdef SIGPWR
500 x = PyInt_FromLong(SIGPWR);
501 PyDict_SetItemString(d, "SIGPWR", x);
502 Py_XDECREF(x);
503 #endif
504 #ifdef SIGIO
505 x = PyInt_FromLong(SIGIO);
506 PyDict_SetItemString(d, "SIGIO", x);
507 Py_XDECREF(x);
508 #endif
509 #ifdef SIGURG
510 x = PyInt_FromLong(SIGURG);
511 PyDict_SetItemString(d, "SIGURG", x);
512 Py_XDECREF(x);
513 #endif
514 #ifdef SIGWINCH
515 x = PyInt_FromLong(SIGWINCH);
516 PyDict_SetItemString(d, "SIGWINCH", x);
517 Py_XDECREF(x);
518 #endif
519 #ifdef SIGPOLL
520 x = PyInt_FromLong(SIGPOLL);
521 PyDict_SetItemString(d, "SIGPOLL", x);
522 Py_XDECREF(x);
523 #endif
524 #ifdef SIGSTOP
525 x = PyInt_FromLong(SIGSTOP);
526 PyDict_SetItemString(d, "SIGSTOP", x);
527 Py_XDECREF(x);
528 #endif
529 #ifdef SIGTSTP
530 x = PyInt_FromLong(SIGTSTP);
531 PyDict_SetItemString(d, "SIGTSTP", x);
532 Py_XDECREF(x);
533 #endif
534 #ifdef SIGCONT
535 x = PyInt_FromLong(SIGCONT);
536 PyDict_SetItemString(d, "SIGCONT", x);
537 Py_XDECREF(x);
538 #endif
539 #ifdef SIGTTIN
540 x = PyInt_FromLong(SIGTTIN);
541 PyDict_SetItemString(d, "SIGTTIN", x);
542 Py_XDECREF(x);
543 #endif
544 #ifdef SIGTTOU
545 x = PyInt_FromLong(SIGTTOU);
546 PyDict_SetItemString(d, "SIGTTOU", x);
547 Py_XDECREF(x);
548 #endif
549 #ifdef SIGVTALRM
550 x = PyInt_FromLong(SIGVTALRM);
551 PyDict_SetItemString(d, "SIGVTALRM", x);
552 Py_XDECREF(x);
553 #endif
554 #ifdef SIGPROF
555 x = PyInt_FromLong(SIGPROF);
556 PyDict_SetItemString(d, "SIGPROF", x);
557 Py_XDECREF(x);
558 #endif
559 #ifdef SIGXCPU
560 x = PyInt_FromLong(SIGXCPU);
561 PyDict_SetItemString(d, "SIGXCPU", x);
562 Py_XDECREF(x);
563 #endif
564 #ifdef SIGXFSZ
565 x = PyInt_FromLong(SIGXFSZ);
566 PyDict_SetItemString(d, "SIGXFSZ", x);
567 Py_XDECREF(x);
568 #endif
569 if (!PyErr_Occurred())
570 return;
572 /* Check for errors */
573 finally:
574 return;
577 static void
578 finisignal()
580 int i;
581 PyObject *func;
583 signal(SIGINT, old_siginthandler);
584 old_siginthandler = SIG_DFL;
586 for (i = 1; i < NSIG; i++) {
587 func = Handlers[i].func;
588 Handlers[i].tripped = 0;
589 Handlers[i].func = NULL;
590 if (i != SIGINT && func != NULL && func != Py_None &&
591 func != DefaultHandler && func != IgnoreHandler)
592 signal(i, SIG_DFL);
593 Py_XDECREF(func);
596 Py_XDECREF(IntHandler);
597 IntHandler = NULL;
598 Py_XDECREF(DefaultHandler);
599 DefaultHandler = NULL;
600 Py_XDECREF(IgnoreHandler);
601 IgnoreHandler = NULL;
606 /* Declared in pyerrors.h */
608 PyErr_CheckSignals()
610 int i;
611 PyObject *f;
613 if (!is_tripped)
614 return 0;
615 #ifdef WITH_THREAD
616 if (get_thread_ident() != main_thread)
617 return 0;
618 #endif
619 if (!(f = PyEval_GetFrame()))
620 f = Py_None;
622 for (i = 1; i < NSIG; i++) {
623 if (Handlers[i].tripped) {
624 PyObject *result = NULL;
625 PyObject *arglist = Py_BuildValue("(iO)", i, f);
626 Handlers[i].tripped = 0;
628 if (arglist) {
629 result = PyEval_CallObject(Handlers[i].func,
630 arglist);
631 Py_DECREF(arglist);
633 if (!result)
634 return -1;
636 Py_DECREF(result);
639 is_tripped = 0;
640 return 0;
644 /* Replacements for intrcheck.c functionality
645 * Declared in pyerrors.h
647 void
648 PyErr_SetInterrupt()
650 is_tripped++;
651 Handlers[SIGINT].tripped = 1;
652 Py_AddPendingCall((int (*) Py_PROTO((ANY *)))PyErr_CheckSignals, NULL);
655 void
656 PyOS_InitInterrupts()
658 initsignal();
659 _PyImport_FixupExtension("signal", "signal");
662 void
663 PyOS_FiniInterrupts()
665 finisignal();
669 PyOS_InterruptOccurred()
671 if (Handlers[SIGINT].tripped) {
672 #ifdef WITH_THREAD
673 if (get_thread_ident() != main_thread)
674 return 0;
675 #endif
676 Handlers[SIGINT].tripped = 0;
677 return 1;
679 return 0;
682 void
683 PyOS_AfterFork()
685 #ifdef WITH_THREAD
686 main_thread = get_thread_ident();
687 main_pid = getpid();
688 #endif