home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Python 1.4 / Python 1.4 source / Modules / signalmodule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-28  |  12.3 KB  |  501 lines  |  [TEXT/CWIE]

  1. /***********************************************************
  2. Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
  3. The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  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.
  16.  
  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.
  20.  
  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.
  29.  
  30. ******************************************************************/
  31.  
  32. /* Signal module -- many thanks to Lance Ellinghaus */
  33.  
  34. #include "Python.h"
  35. #include "intrcheck.h"
  36.  
  37. #include <signal.h>
  38.  
  39. #ifndef SIG_ERR
  40. #define SIG_ERR ((RETSIGTYPE (*)())-1)
  41. #endif
  42.  
  43. #ifndef NSIG
  44. #define NSIG (_SIGMAX + 1)    /* For QNX */
  45. #endif
  46.  
  47.  
  48. /*
  49.    NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS
  50.  
  51.    When threads are supported, we want the following semantics:
  52.  
  53.    - only the main thread can set a signal handler
  54.    - any thread can get a signal handler
  55.    - signals are only delivered to the main thread
  56.  
  57.    I.e. we don't support "synchronous signals" like SIGFPE (catching
  58.    this doesn't make much sense in Python anyway) nor do we support
  59.    signals as a means of inter-thread communication, since not all
  60.    thread implementations support that (at least our thread library
  61.    doesn't).
  62.  
  63.    We still have the problem that in some implementations signals
  64.    generated by the keyboard (e.g. SIGINT) are delivered to all
  65.    threads (e.g. SGI), while in others (e.g. Solaris) such signals are
  66.    delivered to one random thread (an intermediate possibility would
  67.    be to deliver it to the main thread -- POSIX?).  For now, we have
  68.    a working implementation that works in all three cases -- the
  69.    handler ignores signals if getpid() isn't the same as in the main
  70.    thread.  XXX This is a hack.
  71.  
  72. */
  73.  
  74. #ifdef WITH_THREAD
  75. #include "thread.h"
  76. static long main_thread;
  77. static pid_t main_pid;
  78. #endif
  79.  
  80. struct PySignal_SignalArrayStruct {
  81.     int    tripped;
  82.     PyObject *func;
  83. };
  84.  
  85. static struct PySignal_SignalArrayStruct PySignal_SignalHandlerArray[NSIG];
  86. static int PySignal_IsTripped = 0; /* Speed up sigcheck() when none tripped */
  87.  
  88. static PyObject *PySignal_SignalDefaultHandler;
  89. static PyObject *PySignal_SignalIgnoreHandler;
  90. static PyObject *PySignal_DefaultIntHandler;
  91.  
  92. static PyObject *
  93. PySignal_CDefaultIntHandler(self, arg)
  94.     PyObject *self;
  95.     PyObject *arg;
  96. {
  97.     PyErr_SetNone(PyExc_KeyboardInterrupt);
  98.     return (PyObject *)NULL;
  99. }
  100.  
  101. void
  102. PyErr_SetInterrupt()
  103. {
  104.     PySignal_IsTripped++;
  105.     PySignal_SignalHandlerArray[SIGINT].tripped = 1;
  106. }
  107.  
  108. static RETSIGTYPE
  109. PySignal_Handler(sig_num)
  110.     int sig_num;
  111. {
  112. #ifdef WITH_THREAD
  113.     /* See NOTES section above */
  114.     if (getpid() == main_pid) {
  115. #endif
  116.         PySignal_IsTripped++;
  117.         PySignal_SignalHandlerArray[sig_num].tripped = 1;
  118. #ifdef WITH_THREAD
  119.     }
  120. #endif
  121. #ifdef SIGCHLD
  122.     if (sig_num == SIGCHLD) {
  123.         /* To avoid infinite recursion, this signal remains
  124.            reset until explicit re-instated.
  125.            Don't clear the 'func' field as it is our pointer
  126.            to the Python handler... */
  127.         return;
  128.     }
  129. #endif
  130.     (void *)signal(sig_num, &PySignal_Handler);
  131. }
  132.  
  133.  
  134. #ifndef DONT_HAVE_SIG_ALARM
  135. static PyObject *
  136. PySignal_Alarm(self, args)
  137.     PyObject *self; /* Not used */
  138.     PyObject *args;
  139. {
  140.     int t;
  141.     if (!PyArg_Parse(args, "i", &t))
  142.         return (PyObject *)NULL;
  143.     /* alarm() returns the number of seconds remaining */
  144.     return PyInt_FromLong(alarm(t));
  145. }
  146. #endif
  147.  
  148. #ifndef DONT_HAVE_SIG_PAUSE
  149. static PyObject *
  150. PySignal_Pause(self, args)
  151.     PyObject *self; /* Not used */
  152.     PyObject *args;
  153. {
  154.     if (!PyArg_NoArgs(args))
  155.         return NULL;
  156.     Py_BEGIN_ALLOW_THREADS
  157.     pause();
  158.     Py_END_ALLOW_THREADS
  159.     Py_INCREF(Py_None);
  160.     return Py_None;
  161. }
  162. #endif
  163.  
  164. static PyObject *
  165. PySignal_Signal(self, args)
  166.     PyObject *self; /* Not used */
  167.     PyObject *args;
  168. {
  169.     PyObject *obj;
  170.     int sig_num;
  171.     PyObject *old_handler;
  172.     RETSIGTYPE (*func)();
  173.     if (!PyArg_Parse(args, "(iO)", &sig_num, &obj))
  174.         return (PyObject *)NULL;
  175. #ifdef WITH_THREAD
  176.     if (get_thread_ident() != main_thread) {
  177.         PyErr_SetString(PyExc_ValueError,
  178.                 "signal only works in main thread");
  179.         return (PyObject *)NULL;
  180.     }
  181. #endif
  182.     if (sig_num < 1 || sig_num >= NSIG) {
  183.         PyErr_SetString(PyExc_ValueError,
  184.                 "signal number out of range");
  185.         return (PyObject *)NULL;
  186.     }
  187.     if (obj == PySignal_SignalIgnoreHandler)
  188.         func = SIG_IGN;
  189.     else if (obj == PySignal_SignalDefaultHandler)
  190.         func = SIG_DFL;
  191.     else if (!PyCallable_Check(obj)) {
  192.         PyErr_SetString(PyExc_TypeError,
  193. "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
  194.         return (PyObject *)NULL;
  195.     }
  196.     else
  197.         func = PySignal_Handler;
  198.     if (signal(sig_num, func) == SIG_ERR) {
  199.         PyErr_SetFromErrno(PyExc_RuntimeError);
  200.         return (PyObject *)NULL;
  201.     }
  202.     old_handler = PySignal_SignalHandlerArray[sig_num].func;
  203.     PySignal_SignalHandlerArray[sig_num].tripped = 0;
  204.     Py_INCREF(obj);
  205.     PySignal_SignalHandlerArray[sig_num].func = obj;
  206.     return old_handler;
  207. }
  208.  
  209. static PyObject *
  210. PySignal_GetSignal(self, args)
  211.     PyObject *self; /* Not used */
  212.     PyObject *args;
  213. {
  214.     int sig_num;
  215.     PyObject *old_handler;
  216.     if (!PyArg_Parse(args, "i", &sig_num))
  217.         return (PyObject *)NULL;
  218.     if (sig_num < 1 || sig_num >= NSIG) {
  219.         PyErr_SetString(PyExc_ValueError,
  220.                 "signal number out of range");
  221.         return (PyObject *)NULL;
  222.     }
  223.     old_handler = PySignal_SignalHandlerArray[sig_num].func;
  224.     Py_INCREF(old_handler);
  225.     return old_handler;
  226. }
  227.  
  228.  
  229. /* List of functions defined in the module */
  230.  
  231. static PyMethodDef PySignal_methods[] = {
  232. #ifndef DONT_HAVE_SIG_ALARM
  233.     {"alarm",    PySignal_Alarm},
  234. #endif
  235.     {"signal",    PySignal_Signal},
  236.     {"getsignal",    PySignal_GetSignal},
  237. #ifndef DONT_HAVE_SIG_PAUSE
  238.     {"pause",    PySignal_Pause},
  239. #endif
  240.     {"default_int_handler", PySignal_CDefaultIntHandler},
  241.     {NULL,        NULL}        /* sentinel */
  242. };
  243.  
  244. void
  245. initsignal()
  246. {
  247.     PyObject *m, *d, *x;
  248.     int i;
  249.  
  250. #ifdef WITH_THREAD
  251.     main_thread = get_thread_ident();
  252.     main_pid = getpid();
  253. #endif
  254.  
  255.     /* Create the module and add the functions */
  256.     m = Py_InitModule("signal", PySignal_methods);
  257.  
  258.     /* Add some symbolic constants to the module */
  259.     d = PyModule_GetDict(m);
  260.  
  261.     PySignal_SignalDefaultHandler = PyInt_FromLong((long)SIG_DFL);
  262.     PyDict_SetItemString(d, "SIG_DFL", PySignal_SignalDefaultHandler);
  263.     PySignal_SignalIgnoreHandler = PyInt_FromLong((long)SIG_IGN);
  264.     PyDict_SetItemString(d, "SIG_IGN", PySignal_SignalIgnoreHandler);
  265.     PyDict_SetItemString(d, "NSIG", PyInt_FromLong((long)NSIG));
  266.     PySignal_DefaultIntHandler =
  267.         PyDict_GetItemString(d, "default_int_handler");
  268.  
  269.     PySignal_SignalHandlerArray[0].tripped = 0;
  270.     for (i = 1; i < NSIG; i++) {
  271.         RETSIGTYPE (*t)();
  272. #ifdef HAVE_SIGACTION
  273.         struct sigaction act;
  274.         sigaction(i,  0, &act);
  275.         t = act.sa_handler;
  276. #else
  277.         t = signal(i, SIG_IGN);
  278.         signal(i, t);
  279. #endif
  280.         PySignal_SignalHandlerArray[i].tripped = 0;
  281.         if (t == SIG_DFL)
  282.             PySignal_SignalHandlerArray[i].func =
  283.                 PySignal_SignalDefaultHandler;
  284.         else if (t == SIG_IGN)
  285.             PySignal_SignalHandlerArray[i].func =
  286.                 PySignal_SignalIgnoreHandler;
  287.         else
  288.             PySignal_SignalHandlerArray[i].func =
  289.                 Py_None; /* None of our business */
  290.         Py_INCREF(PySignal_SignalHandlerArray[i].func);
  291.     }
  292.     if (PySignal_SignalHandlerArray[SIGINT].func ==
  293.         PySignal_SignalDefaultHandler) {
  294.         /* Install default int handler */
  295.         Py_DECREF(PySignal_SignalHandlerArray[SIGINT].func);
  296.         PySignal_SignalHandlerArray[SIGINT].func =
  297.             PySignal_DefaultIntHandler;
  298.         Py_INCREF(PySignal_DefaultIntHandler);
  299.         signal(SIGINT, &PySignal_Handler);
  300.     }
  301.  
  302. #ifdef SIGHUP
  303.     x = PyInt_FromLong(SIGHUP);
  304.     PyDict_SetItemString(d, "SIGHUP", x);
  305. #endif
  306. #ifdef SIGINT
  307.     x = PyInt_FromLong(SIGINT);
  308.     PyDict_SetItemString(d, "SIGINT", x);
  309. #endif
  310. #ifdef SIGQUIT
  311.     x = PyInt_FromLong(SIGQUIT);
  312.     PyDict_SetItemString(d, "SIGQUIT", x);
  313. #endif
  314. #ifdef SIGILL
  315.     x = PyInt_FromLong(SIGILL);
  316.     PyDict_SetItemString(d, "SIGILL", x);
  317. #endif
  318. #ifdef SIGTRAP
  319.     x = PyInt_FromLong(SIGTRAP);
  320.     PyDict_SetItemString(d, "SIGTRAP", x);
  321. #endif
  322. #ifdef SIGIOT
  323.     x = PyInt_FromLong(SIGIOT);
  324.     PyDict_SetItemString(d, "SIGIOT", x);
  325. #endif
  326. #ifdef SIGABRT
  327.     x = PyInt_FromLong(SIGABRT);
  328.     PyDict_SetItemString(d, "SIGABRT", x);
  329. #endif
  330. #ifdef SIGEMT
  331.     x = PyInt_FromLong(SIGEMT);
  332.     PyDict_SetItemString(d, "SIGEMT", x);
  333. #endif
  334. #ifdef SIGFPE
  335.     x = PyInt_FromLong(SIGFPE);
  336.     PyDict_SetItemString(d, "SIGFPE", x);
  337. #endif
  338. #ifdef SIGKILL
  339.     x = PyInt_FromLong(SIGKILL);
  340.     PyDict_SetItemString(d, "SIGKILL", x);
  341. #endif
  342. #ifdef SIGBUS
  343.     x = PyInt_FromLong(SIGBUS);
  344.     PyDict_SetItemString(d, "SIGBUS", x);
  345. #endif
  346. #ifdef SIGSEGV
  347.     x = PyInt_FromLong(SIGSEGV);
  348.     PyDict_SetItemString(d, "SIGSEGV", x);
  349. #endif
  350. #ifdef SIGSYS
  351.     x = PyInt_FromLong(SIGSYS);
  352.     PyDict_SetItemString(d, "SIGSYS", x);
  353. #endif
  354. #ifdef SIGPIPE
  355.     x = PyInt_FromLong(SIGPIPE);
  356.     PyDict_SetItemString(d, "SIGPIPE", x);
  357. #endif
  358. #ifdef SIGALRM
  359.     x = PyInt_FromLong(SIGALRM);
  360.     PyDict_SetItemString(d, "SIGALRM", x);
  361. #endif
  362. #ifdef SIGTERM
  363.     x = PyInt_FromLong(SIGTERM);
  364.     PyDict_SetItemString(d, "SIGTERM", x);
  365. #endif
  366. #ifdef SIGUSR1
  367.     x = PyInt_FromLong(SIGUSR1);
  368.     PyDict_SetItemString(d, "SIGUSR1", x);
  369. #endif
  370. #ifdef SIGUSR2
  371.     x = PyInt_FromLong(SIGUSR2);
  372.     PyDict_SetItemString(d, "SIGUSR2", x);
  373. #endif
  374. #ifdef SIGCLD
  375.     x = PyInt_FromLong(SIGCLD);
  376.     PyDict_SetItemString(d, "SIGCLD", x);
  377. #endif
  378. #ifdef SIGCHLD
  379.     x = PyInt_FromLong(SIGCHLD);
  380.     PyDict_SetItemString(d, "SIGCHLD", x);
  381. #endif
  382. #ifdef SIGPWR
  383.     x = PyInt_FromLong(SIGPWR);
  384.     PyDict_SetItemString(d, "SIGPWR", x);
  385. #endif
  386. #ifdef SIGIO
  387.     x = PyInt_FromLong(SIGIO);
  388.     PyDict_SetItemString(d, "SIGIO", x);
  389. #endif
  390. #ifdef SIGURG
  391.     x = PyInt_FromLong(SIGURG);
  392.     PyDict_SetItemString(d, "SIGURG", x);
  393. #endif
  394. #ifdef SIGWINCH
  395.     x = PyInt_FromLong(SIGWINCH);
  396.     PyDict_SetItemString(d, "SIGWINCH", x);
  397. #endif
  398. #ifdef SIGPOLL
  399.     x = PyInt_FromLong(SIGPOLL);
  400.     PyDict_SetItemString(d, "SIGPOLL", x);
  401. #endif
  402. #ifdef SIGSTOP
  403.     x = PyInt_FromLong(SIGSTOP);
  404.     PyDict_SetItemString(d, "SIGSTOP", x);
  405. #endif
  406. #ifdef SIGTSTP
  407.     x = PyInt_FromLong(SIGTSTP);
  408.     PyDict_SetItemString(d, "SIGTSTP", x);
  409. #endif
  410. #ifdef SIGCONT
  411.     x = PyInt_FromLong(SIGCONT);
  412.     PyDict_SetItemString(d, "SIGCONT", x);
  413. #endif
  414. #ifdef SIGTTIN
  415.     x = PyInt_FromLong(SIGTTIN);
  416.     PyDict_SetItemString(d, "SIGTTIN", x);
  417. #endif
  418. #ifdef SIGTTOU
  419.     x = PyInt_FromLong(SIGTTOU);
  420.     PyDict_SetItemString(d, "SIGTTOU", x);
  421. #endif
  422. #ifdef SIGVTALRM
  423.     x = PyInt_FromLong(SIGVTALRM);
  424.     PyDict_SetItemString(d, "SIGVTALRM", x);
  425. #endif
  426. #ifdef SIGPROF
  427.     x = PyInt_FromLong(SIGPROF);
  428.     PyDict_SetItemString(d, "SIGPROF", x);
  429. #endif
  430. #ifdef SIGCPU
  431.     x = PyInt_FromLong(SIGCPU);
  432.     PyDict_SetItemString(d, "SIGCPU", x);
  433. #endif
  434. #ifdef SIGFSZ
  435.     x = PyInt_FromLong(SIGFSZ);
  436.     PyDict_SetItemString(d, "SIGFSZ", x);
  437. #endif
  438.     /* Check for errors */
  439.     if (PyErr_Occurred())
  440.         Py_FatalError("can't initialize module signal");
  441. }
  442.  
  443. int
  444. PyErr_CheckSignals()
  445. {
  446.     int i;
  447.     PyObject *f;
  448.     if (!PySignal_IsTripped)
  449.         return 0;
  450. #ifdef WITH_THREAD
  451.     if (get_thread_ident() != main_thread)
  452.         return 0;
  453. #endif
  454.     f = PyEval_GetFrame();
  455.     if (f == (PyObject *)NULL)
  456.         f = Py_None;
  457.     for (i = 1; i < NSIG; i++) {
  458.         if (PySignal_SignalHandlerArray[i].tripped) {
  459.             PyObject *arglist, *result;
  460.             PySignal_SignalHandlerArray[i].tripped = 0;
  461.             arglist = Py_BuildValue("(iO)", i, f);
  462.             if (arglist == (PyObject *)NULL)
  463.                 result = (PyObject *)NULL;
  464.             else {
  465.                 result = PyEval_CallObject(
  466.                  PySignal_SignalHandlerArray[i].func, arglist);
  467.                 Py_DECREF(arglist);
  468.             }
  469.             if (result == (PyObject *)NULL) {
  470.                 return 1;
  471.             } else {
  472.                 Py_DECREF(result);
  473.             }
  474.         }
  475.     }
  476.     PySignal_IsTripped = 0;
  477.     return 0;
  478. }
  479.  
  480. /* Replacement for intrcheck.c functionality */
  481.  
  482. void
  483. PyOS_InitInterrupts ()
  484. {
  485.     initsignal();
  486. }
  487.  
  488. int
  489. PyOS_InterruptOccurred ()
  490. {
  491.     if (PySignal_SignalHandlerArray[SIGINT].tripped) {
  492. #ifdef WITH_THREAD
  493.         if (get_thread_ident() != main_thread)
  494.             return 0;
  495. #endif
  496.         PySignal_SignalHandlerArray[SIGINT].tripped = 0;
  497.         return 1;
  498.     }
  499.     return 0;
  500. }
  501.