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