home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / py2s152.zip / Modules / signalmodule.c < prev    next >
C/C++ Source or Header  |  1999-06-27  |  17KB  |  696 lines

  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. /* 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"
  97. static long main_thread;
  98. static pid_t main_pid;
  99. #endif
  100.  
  101. static struct {
  102.         int tripped;
  103.         PyObject *func;
  104. } Handlers[NSIG];
  105.  
  106. static int is_tripped = 0; /* Speed up sigcheck() when none tripped */
  107.  
  108. static PyObject *DefaultHandler;
  109. static PyObject *IgnoreHandler;
  110. static PyObject *IntHandler;
  111.  
  112. static RETSIGTYPE (*old_siginthandler)() = SIG_DFL;
  113.  
  114.  
  115.  
  116. static PyObject *
  117. signal_default_int_handler(self, arg)
  118.     PyObject *self;
  119.     PyObject *arg;
  120. {
  121.     PyErr_SetNone(PyExc_KeyboardInterrupt);
  122.     return NULL;
  123. }
  124.  
  125. static char default_int_handler_doc[] =
  126. "default_int_handler(...)\n\
  127. \n\
  128. The default handler for SIGINT instated by Python.\n\
  129. It raises KeyboardInterrupt.";
  130.  
  131.  
  132. static RETSIGTYPE
  133. signal_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
  165. static PyObject *
  166. signal_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.  
  177. static char alarm_doc[] =
  178. "alarm(seconds)\n\
  179. \n\
  180. Arrange for SIGALRM to arrive after the given number of seconds.";
  181. #endif
  182.  
  183. #ifdef HAVE_PAUSE
  184. static PyObject *
  185. signal_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. }
  204. static char pause_doc[] =
  205. "pause()\n\
  206. \n\
  207. Wait until a signal arrives.";
  208.  
  209. #endif
  210.  
  211.  
  212. static PyObject *
  213. signal_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.  
  260. static char signal_doc[] =
  261. "signal(sig, action) -> action\n\
  262. \n\
  263. Set the action for the given signal.  The action can be SIG_DFL,\n\
  264. SIG_IGN, or a callable Python object.  The previous action is\n\
  265. returned.  See getsignal() for possible return values.\n\
  266. \n\
  267. *** IMPORTANT NOTICE ***\n\
  268. A signal handler function is called with two arguments:\n\
  269. the first is the signal number, the second is the interrupted stack frame.";
  270.  
  271.  
  272. static PyObject *
  273. signal_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.  
  291. static char getsignal_doc[] =
  292. "getsignal(sig) -> action\n\
  293. \n\
  294. Return the current action for the given signal.  The return value can be:\n\
  295. SIG_IGN -- if the signal is being ignored\n\
  296. SIG_DFL -- if the default action for the signal is in effect\n\
  297. None -- if an unknown handler is in effect\n\
  298. anything else -- the callable Python object used as a handler\n\
  299. ";
  300.  
  301.  
  302. /* List of functions defined in the module */
  303. static 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.  
  319. static char module_doc[] =
  320. "This module provides mechanisms to use signal handlers in Python.\n\
  321. \n\
  322. Functions:\n\
  323. \n\
  324. alarm() -- cause SIGALRM after a specified time [Unix only]\n\
  325. signal() -- set the action for a given signal\n\
  326. getsignal() -- get the signal action for a given signal\n\
  327. pause() -- wait until a signal arrives [Unix only]\n\
  328. default_int_handler() -- default SIGINT handler\n\
  329. \n\
  330. Constants:\n\
  331. \n\
  332. SIG_DFL -- used to refer to the system default handler\n\
  333. SIG_IGN -- used to ignore the signal\n\
  334. NSIG -- number of defined signals\n\
  335. \n\
  336. SIGINT, SIGTERM, etc. -- signal numbers\n\
  337. \n\
  338. *** IMPORTANT NOTICE ***\n\
  339. A signal handler function is called with two arguments:\n\
  340. the first is the signal number, the second is the interrupted stack frame.";
  341.  
  342. DL_EXPORT(void)
  343. initsignal()
  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 = PyInt_FromLong((long)SIG_DFL);
  360.         if (!x || PyDict_SetItemString(d, "SIG_DFL", x) < 0)
  361.                 goto finally;
  362.  
  363.     x = IgnoreHandler = PyInt_FromLong((long)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.  
  583. static void
  584. finisignal()
  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 */
  613. int
  614. PyErr_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.  */
  653. void
  654. PyErr_SetInterrupt()
  655. {
  656.     is_tripped++;
  657.     Handlers[SIGINT].tripped = 1;
  658.     Py_AddPendingCall((int (*) Py_PROTO((ANY *)))PyErr_CheckSignals, NULL);
  659. }
  660.  
  661. void
  662. PyOS_InitInterrupts()
  663. {
  664.     initsignal();
  665.     _PyImport_FixupExtension("signal", "signal");
  666. }
  667.  
  668. void
  669. PyOS_FiniInterrupts()
  670. {
  671.     finisignal();
  672. }
  673.  
  674. int
  675. PyOS_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.  
  688. void
  689. PyOS_AfterFork()
  690. {
  691. #ifdef WITH_THREAD
  692.     main_thread = PyThread_get_thread_ident();
  693.     main_pid = getpid();
  694. #endif
  695. }
  696.