+++ /dev/null
-\r
-/* Signal module -- many thanks to Lance Ellinghaus */\r
-\r
-/* XXX Signals should be recorded per thread, now we have thread state. */\r
-\r
-#include "Python.h"\r
-#include "intrcheck.h"\r
-\r
-#ifdef MS_WINDOWS\r
-#include <Windows.h>\r
-#ifdef HAVE_PROCESS_H\r
-#include <process.h>\r
-#endif\r
-#endif\r
-\r
-#ifdef HAVE_SIGNAL_H\r
-#include <signal.h>\r
-#endif\r
-#ifdef HAVE_SYS_STAT_H\r
-#include <sys/stat.h>\r
-#endif\r
-#ifdef HAVE_SYS_TIME_H\r
-#include <sys/time.h>\r
-#endif\r
-\r
-#ifndef SIG_ERR\r
-#define SIG_ERR ((PyOS_sighandler_t)(-1))\r
-#endif\r
-\r
-#if defined(PYOS_OS2) && !defined(PYCC_GCC)\r
-#define NSIG 12\r
-#include <process.h>\r
-#endif\r
-\r
-#ifndef NSIG\r
-# if defined(_NSIG)\r
-# define NSIG _NSIG /* For BSD/SysV */\r
-# elif defined(_SIGMAX)\r
-# define NSIG (_SIGMAX + 1) /* For QNX */\r
-# elif defined(SIGMAX)\r
-# define NSIG (SIGMAX + 1) /* For djgpp */\r
-# else\r
-# define NSIG 64 /* Use a reasonable default value */\r
-# endif\r
-#endif\r
-\r
-\r
-/*\r
- NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS\r
-\r
- When threads are supported, we want the following semantics:\r
-\r
- - only the main thread can set a signal handler\r
- - any thread can get a signal handler\r
- - signals are only delivered to the main thread\r
-\r
- I.e. we don't support "synchronous signals" like SIGFPE (catching\r
- this doesn't make much sense in Python anyway) nor do we support\r
- signals as a means of inter-thread communication, since not all\r
- thread implementations support that (at least our thread library\r
- doesn't).\r
-\r
- We still have the problem that in some implementations signals\r
- generated by the keyboard (e.g. SIGINT) are delivered to all\r
- threads (e.g. SGI), while in others (e.g. Solaris) such signals are\r
- delivered to one random thread (an intermediate possibility would\r
- be to deliver it to the main thread -- POSIX?). For now, we have\r
- a working implementation that works in all three cases -- the\r
- handler ignores signals if getpid() isn't the same as in the main\r
- thread. XXX This is a hack.\r
-\r
- GNU pth is a user-space threading library, and as such, all threads\r
- run within the same process. In this case, if the currently running\r
- thread is not the main_thread, send the signal to the main_thread.\r
-*/\r
-\r
-#ifdef WITH_THREAD\r
-#include <sys/types.h> /* For pid_t */\r
-#include "pythread.h"\r
-static long main_thread;\r
-static pid_t main_pid;\r
-#endif\r
-\r
-static struct {\r
- int tripped;\r
- PyObject *func;\r
-} Handlers[NSIG];\r
-\r
-static sig_atomic_t wakeup_fd = -1;\r
-\r
-/* Speed up sigcheck() when none tripped */\r
-static volatile sig_atomic_t is_tripped = 0;\r
-\r
-static PyObject *DefaultHandler;\r
-static PyObject *IgnoreHandler;\r
-static PyObject *IntHandler;\r
-\r
-/* On Solaris 8, gcc will produce a warning that the function\r
- declaration is not a prototype. This is caused by the definition of\r
- SIG_DFL as (void (*)())0; the correct declaration would have been\r
- (void (*)(int))0. */\r
-\r
-static PyOS_sighandler_t old_siginthandler = SIG_DFL;\r
-\r
-#ifdef HAVE_GETITIMER\r
-static PyObject *ItimerError;\r
-\r
-/* auxiliary functions for setitimer/getitimer */\r
-static void\r
-timeval_from_double(double d, struct timeval *tv)\r
-{\r
- tv->tv_sec = floor(d);\r
- tv->tv_usec = fmod(d, 1.0) * 1000000.0;\r
-}\r
-\r
-Py_LOCAL_INLINE(double)\r
-double_from_timeval(struct timeval *tv)\r
-{\r
- return tv->tv_sec + (double)(tv->tv_usec / 1000000.0);\r
-}\r
-\r
-static PyObject *\r
-itimer_retval(struct itimerval *iv)\r
-{\r
- PyObject *r, *v;\r
-\r
- r = PyTuple_New(2);\r
- if (r == NULL)\r
- return NULL;\r
-\r
- if(!(v = PyFloat_FromDouble(double_from_timeval(&iv->it_value)))) {\r
- Py_DECREF(r);\r
- return NULL;\r
- }\r
-\r
- PyTuple_SET_ITEM(r, 0, v);\r
-\r
- if(!(v = PyFloat_FromDouble(double_from_timeval(&iv->it_interval)))) {\r
- Py_DECREF(r);\r
- return NULL;\r
- }\r
-\r
- PyTuple_SET_ITEM(r, 1, v);\r
-\r
- return r;\r
-}\r
-#endif\r
-\r
-static PyObject *\r
-signal_default_int_handler(PyObject *self, PyObject *args)\r
-{\r
- PyErr_SetNone(PyExc_KeyboardInterrupt);\r
- return NULL;\r
-}\r
-\r
-PyDoc_STRVAR(default_int_handler_doc,\r
-"default_int_handler(...)\n\\r
-\n\\r
-The default handler for SIGINT installed by Python.\n\\r
-It raises KeyboardInterrupt.");\r
-\r
-\r
-static int\r
-checksignals_witharg(void * unused)\r
-{\r
- return PyErr_CheckSignals();\r
-}\r
-\r
-static void\r
-trip_signal(int sig_num)\r
-{\r
- Handlers[sig_num].tripped = 1;\r
- if (is_tripped)\r
- return;\r
- /* Set is_tripped after setting .tripped, as it gets\r
- cleared in PyErr_CheckSignals() before .tripped. */\r
- is_tripped = 1;\r
- Py_AddPendingCall(checksignals_witharg, NULL);\r
- if (wakeup_fd != -1)\r
- write(wakeup_fd, "\0", 1);\r
-}\r
-\r
-static void\r
-signal_handler(int sig_num)\r
-{\r
- int save_errno = errno;\r
-\r
-#if defined(WITH_THREAD) && defined(WITH_PTH)\r
- if (PyThread_get_thread_ident() != main_thread) {\r
- pth_raise(*(pth_t *) main_thread, sig_num);\r
- }\r
- else\r
-#endif\r
- {\r
-#ifdef WITH_THREAD\r
- /* See NOTES section above */\r
- if (getpid() == main_pid)\r
-#endif\r
- {\r
- trip_signal(sig_num);\r
- }\r
-\r
-#ifndef HAVE_SIGACTION\r
-#ifdef SIGCHLD\r
- /* To avoid infinite recursion, this signal remains\r
- reset until explicit re-instated.\r
- Don't clear the 'func' field as it is our pointer\r
- to the Python handler... */\r
- if (sig_num != SIGCHLD)\r
-#endif\r
- /* If the handler was not set up with sigaction, reinstall it. See\r
- * Python/pythonrun.c for the implementation of PyOS_setsig which\r
- * makes this true. See also issue8354. */\r
- PyOS_setsig(sig_num, signal_handler);\r
-#endif\r
- }\r
-\r
- /* Issue #10311: asynchronously executing signal handlers should not\r
- mutate errno under the feet of unsuspecting C code. */\r
- errno = save_errno;\r
-}\r
-\r
-\r
-#ifdef HAVE_ALARM\r
-static PyObject *\r
-signal_alarm(PyObject *self, PyObject *args)\r
-{\r
- int t;\r
- if (!PyArg_ParseTuple(args, "i:alarm", &t))\r
- return NULL;\r
- /* alarm() returns the number of seconds remaining */\r
- return PyInt_FromLong((long)alarm(t));\r
-}\r
-\r
-PyDoc_STRVAR(alarm_doc,\r
-"alarm(seconds)\n\\r
-\n\\r
-Arrange for SIGALRM to arrive after the given number of seconds.");\r
-#endif\r
-\r
-#ifdef HAVE_PAUSE\r
-static PyObject *\r
-signal_pause(PyObject *self)\r
-{\r
- Py_BEGIN_ALLOW_THREADS\r
- (void)pause();\r
- Py_END_ALLOW_THREADS\r
- /* make sure that any exceptions that got raised are propagated\r
- * back into Python\r
- */\r
- if (PyErr_CheckSignals())\r
- return NULL;\r
-\r
- Py_INCREF(Py_None);\r
- return Py_None;\r
-}\r
-PyDoc_STRVAR(pause_doc,\r
-"pause()\n\\r
-\n\\r
-Wait until a signal arrives.");\r
-\r
-#endif\r
-\r
-\r
-static PyObject *\r
-signal_signal(PyObject *self, PyObject *args)\r
-{\r
- PyObject *obj;\r
- int sig_num;\r
- PyObject *old_handler;\r
- void (*func)(int);\r
- if (!PyArg_ParseTuple(args, "iO:signal", &sig_num, &obj))\r
- return NULL;\r
-#ifdef MS_WINDOWS\r
- /* Validate that sig_num is one of the allowable signals */\r
- switch (sig_num) {\r
- case SIGABRT: break;\r
-#ifdef SIGBREAK\r
- /* Issue #10003: SIGBREAK is not documented as permitted, but works\r
- and corresponds to CTRL_BREAK_EVENT. */\r
- case SIGBREAK: break;\r
-#endif\r
- case SIGFPE: break;\r
- case SIGILL: break;\r
- case SIGINT: break;\r
- case SIGSEGV: break;\r
- case SIGTERM: break;\r
- default:\r
- PyErr_SetString(PyExc_ValueError, "invalid signal value");\r
- return NULL;\r
- }\r
-#endif\r
-#ifdef WITH_THREAD\r
- if (PyThread_get_thread_ident() != main_thread) {\r
- PyErr_SetString(PyExc_ValueError,\r
- "signal only works in main thread");\r
- return NULL;\r
- }\r
-#endif\r
- if (sig_num < 1 || sig_num >= NSIG) {\r
- PyErr_SetString(PyExc_ValueError,\r
- "signal number out of range");\r
- return NULL;\r
- }\r
- if (obj == IgnoreHandler)\r
- func = SIG_IGN;\r
- else if (obj == DefaultHandler)\r
- func = SIG_DFL;\r
- else if (!PyCallable_Check(obj)) {\r
- PyErr_SetString(PyExc_TypeError,\r
-"signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");\r
- return NULL;\r
- }\r
- else\r
- func = signal_handler;\r
- if (PyOS_setsig(sig_num, func) == SIG_ERR) {\r
- PyErr_SetFromErrno(PyExc_RuntimeError);\r
- return NULL;\r
- }\r
- old_handler = Handlers[sig_num].func;\r
- Handlers[sig_num].tripped = 0;\r
- Py_INCREF(obj);\r
- Handlers[sig_num].func = obj;\r
- if (old_handler != NULL)\r
- return old_handler;\r
- else\r
- Py_RETURN_NONE;\r
-}\r
-\r
-PyDoc_STRVAR(signal_doc,\r
-"signal(sig, action) -> action\n\\r
-\n\\r
-Set the action for the given signal. The action can be SIG_DFL,\n\\r
-SIG_IGN, or a callable Python object. The previous action is\n\\r
-returned. See getsignal() for possible return values.\n\\r
-\n\\r
-*** IMPORTANT NOTICE ***\n\\r
-A signal handler function is called with two arguments:\n\\r
-the first is the signal number, the second is the interrupted stack frame.");\r
-\r
-\r
-static PyObject *\r
-signal_getsignal(PyObject *self, PyObject *args)\r
-{\r
- int sig_num;\r
- PyObject *old_handler;\r
- if (!PyArg_ParseTuple(args, "i:getsignal", &sig_num))\r
- return NULL;\r
- if (sig_num < 1 || sig_num >= NSIG) {\r
- PyErr_SetString(PyExc_ValueError,\r
- "signal number out of range");\r
- return NULL;\r
- }\r
- old_handler = Handlers[sig_num].func;\r
- if (old_handler != NULL) {\r
- Py_INCREF(old_handler);\r
- return old_handler;\r
- }\r
- else {\r
- Py_RETURN_NONE;\r
- }\r
-}\r
-\r
-PyDoc_STRVAR(getsignal_doc,\r
-"getsignal(sig) -> action\n\\r
-\n\\r
-Return the current action for the given signal. The return value can be:\n\\r
-SIG_IGN -- if the signal is being ignored\n\\r
-SIG_DFL -- if the default action for the signal is in effect\n\\r
-None -- if an unknown handler is in effect\n\\r
-anything else -- the callable Python object used as a handler");\r
-\r
-#ifdef HAVE_SIGINTERRUPT\r
-PyDoc_STRVAR(siginterrupt_doc,\r
-"siginterrupt(sig, flag) -> None\n\\r
-change system call restart behaviour: if flag is False, system calls\n\\r
-will be restarted when interrupted by signal sig, else system calls\n\\r
-will be interrupted.");\r
-\r
-static PyObject *\r
-signal_siginterrupt(PyObject *self, PyObject *args)\r
-{\r
- int sig_num;\r
- int flag;\r
-\r
- if (!PyArg_ParseTuple(args, "ii:siginterrupt", &sig_num, &flag))\r
- return NULL;\r
- if (sig_num < 1 || sig_num >= NSIG) {\r
- PyErr_SetString(PyExc_ValueError,\r
- "signal number out of range");\r
- return NULL;\r
- }\r
- if (siginterrupt(sig_num, flag)<0) {\r
- PyErr_SetFromErrno(PyExc_RuntimeError);\r
- return NULL;\r
- }\r
-\r
- Py_INCREF(Py_None);\r
- return Py_None;\r
-}\r
-\r
-#endif\r
-\r
-static PyObject *\r
-signal_set_wakeup_fd(PyObject *self, PyObject *args)\r
-{\r
- struct stat buf;\r
- int fd, old_fd;\r
- if (!PyArg_ParseTuple(args, "i:set_wakeup_fd", &fd))\r
- return NULL;\r
-#ifdef WITH_THREAD\r
- if (PyThread_get_thread_ident() != main_thread) {\r
- PyErr_SetString(PyExc_ValueError,\r
- "set_wakeup_fd only works in main thread");\r
- return NULL;\r
- }\r
-#endif\r
- if (fd != -1 && (!_PyVerify_fd(fd) || fstat(fd, &buf) != 0)) {\r
- PyErr_SetString(PyExc_ValueError, "invalid fd");\r
- return NULL;\r
- }\r
- old_fd = wakeup_fd;\r
- wakeup_fd = fd;\r
- return PyLong_FromLong(old_fd);\r
-}\r
-\r
-PyDoc_STRVAR(set_wakeup_fd_doc,\r
-"set_wakeup_fd(fd) -> fd\n\\r
-\n\\r
-Sets the fd to be written to (with '\\0') when a signal\n\\r
-comes in. A library can use this to wakeup select or poll.\n\\r
-The previous fd is returned.\n\\r
-\n\\r
-The fd must be non-blocking.");\r
-\r
-/* C API for the same, without all the error checking */\r
-int\r
-PySignal_SetWakeupFd(int fd)\r
-{\r
- int old_fd = wakeup_fd;\r
- if (fd < 0)\r
- fd = -1;\r
- wakeup_fd = fd;\r
- return old_fd;\r
-}\r
-\r
-\r
-#ifdef HAVE_SETITIMER\r
-static PyObject *\r
-signal_setitimer(PyObject *self, PyObject *args)\r
-{\r
- double first;\r
- double interval = 0;\r
- int which;\r
- struct itimerval new, old;\r
-\r
- if(!PyArg_ParseTuple(args, "id|d:setitimer", &which, &first, &interval))\r
- return NULL;\r
-\r
- timeval_from_double(first, &new.it_value);\r
- timeval_from_double(interval, &new.it_interval);\r
- /* Let OS check "which" value */\r
- if (setitimer(which, &new, &old) != 0) {\r
- PyErr_SetFromErrno(ItimerError);\r
- return NULL;\r
- }\r
-\r
- return itimer_retval(&old);\r
-}\r
-\r
-PyDoc_STRVAR(setitimer_doc,\r
-"setitimer(which, seconds[, interval])\n\\r
-\n\\r
-Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL\n\\r
-or ITIMER_PROF) to fire after value seconds and after\n\\r
-that every interval seconds.\n\\r
-The itimer can be cleared by setting seconds to zero.\n\\r
-\n\\r
-Returns old values as a tuple: (delay, interval).");\r
-#endif\r
-\r
-\r
-#ifdef HAVE_GETITIMER\r
-static PyObject *\r
-signal_getitimer(PyObject *self, PyObject *args)\r
-{\r
- int which;\r
- struct itimerval old;\r
-\r
- if (!PyArg_ParseTuple(args, "i:getitimer", &which))\r
- return NULL;\r
-\r
- if (getitimer(which, &old) != 0) {\r
- PyErr_SetFromErrno(ItimerError);\r
- return NULL;\r
- }\r
-\r
- return itimer_retval(&old);\r
-}\r
-\r
-PyDoc_STRVAR(getitimer_doc,\r
-"getitimer(which)\n\\r
-\n\\r
-Returns current value of given itimer.");\r
-#endif\r
-\r
-\r
-/* List of functions defined in the module */\r
-static PyMethodDef signal_methods[] = {\r
-#ifdef HAVE_ALARM\r
- {"alarm", signal_alarm, METH_VARARGS, alarm_doc},\r
-#endif\r
-#ifdef HAVE_SETITIMER\r
- {"setitimer", signal_setitimer, METH_VARARGS, setitimer_doc},\r
-#endif\r
-#ifdef HAVE_GETITIMER\r
- {"getitimer", signal_getitimer, METH_VARARGS, getitimer_doc},\r
-#endif\r
- {"signal", signal_signal, METH_VARARGS, signal_doc},\r
- {"getsignal", signal_getsignal, METH_VARARGS, getsignal_doc},\r
- {"set_wakeup_fd", signal_set_wakeup_fd, METH_VARARGS, set_wakeup_fd_doc},\r
-#ifdef HAVE_SIGINTERRUPT\r
- {"siginterrupt", signal_siginterrupt, METH_VARARGS, siginterrupt_doc},\r
-#endif\r
-#ifdef HAVE_PAUSE\r
- {"pause", (PyCFunction)signal_pause,\r
- METH_NOARGS,pause_doc},\r
-#endif\r
- {"default_int_handler", signal_default_int_handler,\r
- METH_VARARGS, default_int_handler_doc},\r
- {NULL, NULL} /* sentinel */\r
-};\r
-\r
-\r
-PyDoc_STRVAR(module_doc,\r
-"This module provides mechanisms to use signal handlers in Python.\n\\r
-\n\\r
-Functions:\n\\r
-\n\\r
-alarm() -- cause SIGALRM after a specified time [Unix only]\n\\r
-setitimer() -- cause a signal (described below) after a specified\n\\r
- float time and the timer may restart then [Unix only]\n\\r
-getitimer() -- get current value of timer [Unix only]\n\\r
-signal() -- set the action for a given signal\n\\r
-getsignal() -- get the signal action for a given signal\n\\r
-pause() -- wait until a signal arrives [Unix only]\n\\r
-default_int_handler() -- default SIGINT handler\n\\r
-\n\\r
-signal constants:\n\\r
-SIG_DFL -- used to refer to the system default handler\n\\r
-SIG_IGN -- used to ignore the signal\n\\r
-NSIG -- number of defined signals\n\\r
-SIGINT, SIGTERM, etc. -- signal numbers\n\\r
-\n\\r
-itimer constants:\n\\r
-ITIMER_REAL -- decrements in real time, and delivers SIGALRM upon\n\\r
- expiration\n\\r
-ITIMER_VIRTUAL -- decrements only when the process is executing,\n\\r
- and delivers SIGVTALRM upon expiration\n\\r
-ITIMER_PROF -- decrements both when the process is executing and\n\\r
- when the system is executing on behalf of the process.\n\\r
- Coupled with ITIMER_VIRTUAL, this timer is usually\n\\r
- used to profile the time spent by the application\n\\r
- in user and kernel space. SIGPROF is delivered upon\n\\r
- expiration.\n\\r
-\n\n\\r
-*** IMPORTANT NOTICE ***\n\\r
-A signal handler function is called with two arguments:\n\\r
-the first is the signal number, the second is the interrupted stack frame.");\r
-\r
-PyMODINIT_FUNC\r
-initsignal(void)\r
-{\r
- PyObject *m, *d, *x;\r
- int i;\r
-\r
-#ifdef WITH_THREAD\r
- main_thread = PyThread_get_thread_ident();\r
- main_pid = getpid();\r
-#endif\r
-\r
- /* Create the module and add the functions */\r
- m = Py_InitModule3("signal", signal_methods, module_doc);\r
- if (m == NULL)\r
- return;\r
-\r
- /* Add some symbolic constants to the module */\r
- d = PyModule_GetDict(m);\r
-\r
- x = DefaultHandler = PyLong_FromVoidPtr((void *)SIG_DFL);\r
- if (!x || PyDict_SetItemString(d, "SIG_DFL", x) < 0)\r
- goto finally;\r
-\r
- x = IgnoreHandler = PyLong_FromVoidPtr((void *)SIG_IGN);\r
- if (!x || PyDict_SetItemString(d, "SIG_IGN", x) < 0)\r
- goto finally;\r
-\r
- x = PyInt_FromLong((long)NSIG);\r
- if (!x || PyDict_SetItemString(d, "NSIG", x) < 0)\r
- goto finally;\r
- Py_DECREF(x);\r
-\r
- x = IntHandler = PyDict_GetItemString(d, "default_int_handler");\r
- if (!x)\r
- goto finally;\r
- Py_INCREF(IntHandler);\r
-\r
- Handlers[0].tripped = 0;\r
- for (i = 1; i < NSIG; i++) {\r
- void (*t)(int);\r
- t = PyOS_getsig(i);\r
- Handlers[i].tripped = 0;\r
- if (t == SIG_DFL)\r
- Handlers[i].func = DefaultHandler;\r
- else if (t == SIG_IGN)\r
- Handlers[i].func = IgnoreHandler;\r
- else\r
- Handlers[i].func = Py_None; /* None of our business */\r
- Py_INCREF(Handlers[i].func);\r
- }\r
- if (Handlers[SIGINT].func == DefaultHandler) {\r
- /* Install default int handler */\r
- Py_INCREF(IntHandler);\r
- Py_DECREF(Handlers[SIGINT].func);\r
- Handlers[SIGINT].func = IntHandler;\r
- old_siginthandler = PyOS_setsig(SIGINT, signal_handler);\r
- }\r
-\r
-#ifdef SIGHUP\r
- x = PyInt_FromLong(SIGHUP);\r
- PyDict_SetItemString(d, "SIGHUP", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGINT\r
- x = PyInt_FromLong(SIGINT);\r
- PyDict_SetItemString(d, "SIGINT", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGBREAK\r
- x = PyInt_FromLong(SIGBREAK);\r
- PyDict_SetItemString(d, "SIGBREAK", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGQUIT\r
- x = PyInt_FromLong(SIGQUIT);\r
- PyDict_SetItemString(d, "SIGQUIT", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGILL\r
- x = PyInt_FromLong(SIGILL);\r
- PyDict_SetItemString(d, "SIGILL", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGTRAP\r
- x = PyInt_FromLong(SIGTRAP);\r
- PyDict_SetItemString(d, "SIGTRAP", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGIOT\r
- x = PyInt_FromLong(SIGIOT);\r
- PyDict_SetItemString(d, "SIGIOT", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGABRT\r
- x = PyInt_FromLong(SIGABRT);\r
- PyDict_SetItemString(d, "SIGABRT", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGEMT\r
- x = PyInt_FromLong(SIGEMT);\r
- PyDict_SetItemString(d, "SIGEMT", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGFPE\r
- x = PyInt_FromLong(SIGFPE);\r
- PyDict_SetItemString(d, "SIGFPE", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGKILL\r
- x = PyInt_FromLong(SIGKILL);\r
- PyDict_SetItemString(d, "SIGKILL", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGBUS\r
- x = PyInt_FromLong(SIGBUS);\r
- PyDict_SetItemString(d, "SIGBUS", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGSEGV\r
- x = PyInt_FromLong(SIGSEGV);\r
- PyDict_SetItemString(d, "SIGSEGV", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGSYS\r
- x = PyInt_FromLong(SIGSYS);\r
- PyDict_SetItemString(d, "SIGSYS", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGPIPE\r
- x = PyInt_FromLong(SIGPIPE);\r
- PyDict_SetItemString(d, "SIGPIPE", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGALRM\r
- x = PyInt_FromLong(SIGALRM);\r
- PyDict_SetItemString(d, "SIGALRM", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGTERM\r
- x = PyInt_FromLong(SIGTERM);\r
- PyDict_SetItemString(d, "SIGTERM", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGUSR1\r
- x = PyInt_FromLong(SIGUSR1);\r
- PyDict_SetItemString(d, "SIGUSR1", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGUSR2\r
- x = PyInt_FromLong(SIGUSR2);\r
- PyDict_SetItemString(d, "SIGUSR2", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGCLD\r
- x = PyInt_FromLong(SIGCLD);\r
- PyDict_SetItemString(d, "SIGCLD", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGCHLD\r
- x = PyInt_FromLong(SIGCHLD);\r
- PyDict_SetItemString(d, "SIGCHLD", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGPWR\r
- x = PyInt_FromLong(SIGPWR);\r
- PyDict_SetItemString(d, "SIGPWR", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGIO\r
- x = PyInt_FromLong(SIGIO);\r
- PyDict_SetItemString(d, "SIGIO", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGURG\r
- x = PyInt_FromLong(SIGURG);\r
- PyDict_SetItemString(d, "SIGURG", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGWINCH\r
- x = PyInt_FromLong(SIGWINCH);\r
- PyDict_SetItemString(d, "SIGWINCH", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGPOLL\r
- x = PyInt_FromLong(SIGPOLL);\r
- PyDict_SetItemString(d, "SIGPOLL", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGSTOP\r
- x = PyInt_FromLong(SIGSTOP);\r
- PyDict_SetItemString(d, "SIGSTOP", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGTSTP\r
- x = PyInt_FromLong(SIGTSTP);\r
- PyDict_SetItemString(d, "SIGTSTP", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGCONT\r
- x = PyInt_FromLong(SIGCONT);\r
- PyDict_SetItemString(d, "SIGCONT", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGTTIN\r
- x = PyInt_FromLong(SIGTTIN);\r
- PyDict_SetItemString(d, "SIGTTIN", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGTTOU\r
- x = PyInt_FromLong(SIGTTOU);\r
- PyDict_SetItemString(d, "SIGTTOU", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGVTALRM\r
- x = PyInt_FromLong(SIGVTALRM);\r
- PyDict_SetItemString(d, "SIGVTALRM", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGPROF\r
- x = PyInt_FromLong(SIGPROF);\r
- PyDict_SetItemString(d, "SIGPROF", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGXCPU\r
- x = PyInt_FromLong(SIGXCPU);\r
- PyDict_SetItemString(d, "SIGXCPU", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGXFSZ\r
- x = PyInt_FromLong(SIGXFSZ);\r
- PyDict_SetItemString(d, "SIGXFSZ", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGRTMIN\r
- x = PyInt_FromLong(SIGRTMIN);\r
- PyDict_SetItemString(d, "SIGRTMIN", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGRTMAX\r
- x = PyInt_FromLong(SIGRTMAX);\r
- PyDict_SetItemString(d, "SIGRTMAX", x);\r
- Py_XDECREF(x);\r
-#endif\r
-#ifdef SIGINFO\r
- x = PyInt_FromLong(SIGINFO);\r
- PyDict_SetItemString(d, "SIGINFO", x);\r
- Py_XDECREF(x);\r
-#endif\r
-\r
-#ifdef ITIMER_REAL\r
- x = PyLong_FromLong(ITIMER_REAL);\r
- PyDict_SetItemString(d, "ITIMER_REAL", x);\r
- Py_DECREF(x);\r
-#endif\r
-#ifdef ITIMER_VIRTUAL\r
- x = PyLong_FromLong(ITIMER_VIRTUAL);\r
- PyDict_SetItemString(d, "ITIMER_VIRTUAL", x);\r
- Py_DECREF(x);\r
-#endif\r
-#ifdef ITIMER_PROF\r
- x = PyLong_FromLong(ITIMER_PROF);\r
- PyDict_SetItemString(d, "ITIMER_PROF", x);\r
- Py_DECREF(x);\r
-#endif\r
-\r
-#if defined (HAVE_SETITIMER) || defined (HAVE_GETITIMER)\r
- ItimerError = PyErr_NewException("signal.ItimerError",\r
- PyExc_IOError, NULL);\r
- if (ItimerError != NULL)\r
- PyDict_SetItemString(d, "ItimerError", ItimerError);\r
-#endif\r
-\r
-#ifdef CTRL_C_EVENT\r
- x = PyInt_FromLong(CTRL_C_EVENT);\r
- PyDict_SetItemString(d, "CTRL_C_EVENT", x);\r
- Py_DECREF(x);\r
-#endif\r
-\r
-#ifdef CTRL_BREAK_EVENT\r
- x = PyInt_FromLong(CTRL_BREAK_EVENT);\r
- PyDict_SetItemString(d, "CTRL_BREAK_EVENT", x);\r
- Py_DECREF(x);\r
-#endif\r
-\r
- if (!PyErr_Occurred())\r
- return;\r
-\r
- /* Check for errors */\r
- finally:\r
- return;\r
-}\r
-\r
-static void\r
-finisignal(void)\r
-{\r
- int i;\r
- PyObject *func;\r
-\r
- PyOS_setsig(SIGINT, old_siginthandler);\r
- old_siginthandler = SIG_DFL;\r
-\r
- for (i = 1; i < NSIG; i++) {\r
- func = Handlers[i].func;\r
- Handlers[i].tripped = 0;\r
- Handlers[i].func = NULL;\r
- if (i != SIGINT && func != NULL && func != Py_None &&\r
- func != DefaultHandler && func != IgnoreHandler)\r
- PyOS_setsig(i, SIG_DFL);\r
- Py_XDECREF(func);\r
- }\r
-\r
- Py_XDECREF(IntHandler);\r
- IntHandler = NULL;\r
- Py_XDECREF(DefaultHandler);\r
- DefaultHandler = NULL;\r
- Py_XDECREF(IgnoreHandler);\r
- IgnoreHandler = NULL;\r
-}\r
-\r
-\r
-/* Declared in pyerrors.h */\r
-int\r
-PyErr_CheckSignals(void)\r
-{\r
- int i;\r
- PyObject *f;\r
-\r
- if (!is_tripped)\r
- return 0;\r
-\r
-#ifdef WITH_THREAD\r
- if (PyThread_get_thread_ident() != main_thread)\r
- return 0;\r
-#endif\r
-\r
- /*\r
- * The is_tripped variable is meant to speed up the calls to\r
- * PyErr_CheckSignals (both directly or via pending calls) when no\r
- * signal has arrived. This variable is set to 1 when a signal arrives\r
- * and it is set to 0 here, when we know some signals arrived. This way\r
- * we can run the registered handlers with no signals blocked.\r
- *\r
- * NOTE: with this approach we can have a situation where is_tripped is\r
- * 1 but we have no more signals to handle (Handlers[i].tripped\r
- * is 0 for every signal i). This won't do us any harm (except\r
- * we're gonna spent some cycles for nothing). This happens when\r
- * we receive a signal i after we zero is_tripped and before we\r
- * check Handlers[i].tripped.\r
- */\r
- is_tripped = 0;\r
-\r
- if (!(f = (PyObject *)PyEval_GetFrame()))\r
- f = Py_None;\r
-\r
- for (i = 1; i < NSIG; i++) {\r
- if (Handlers[i].tripped) {\r
- PyObject *result = NULL;\r
- PyObject *arglist = Py_BuildValue("(iO)", i, f);\r
- Handlers[i].tripped = 0;\r
-\r
- if (arglist) {\r
- result = PyEval_CallObject(Handlers[i].func,\r
- arglist);\r
- Py_DECREF(arglist);\r
- }\r
- if (!result)\r
- return -1;\r
-\r
- Py_DECREF(result);\r
- }\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-\r
-/* Replacements for intrcheck.c functionality\r
- * Declared in pyerrors.h\r
- */\r
-void\r
-PyErr_SetInterrupt(void)\r
-{\r
- trip_signal(SIGINT);\r
-}\r
-\r
-void\r
-PyOS_InitInterrupts(void)\r
-{\r
- initsignal();\r
- _PyImport_FixupExtension("signal", "signal");\r
-}\r
-\r
-void\r
-PyOS_FiniInterrupts(void)\r
-{\r
- finisignal();\r
-}\r
-\r
-int\r
-PyOS_InterruptOccurred(void)\r
-{\r
- if (Handlers[SIGINT].tripped) {\r
-#ifdef WITH_THREAD\r
- if (PyThread_get_thread_ident() != main_thread)\r
- return 0;\r
-#endif\r
- Handlers[SIGINT].tripped = 0;\r
- return 1;\r
- }\r
- return 0;\r
-}\r
-\r
-static void\r
-_clear_pending_signals(void)\r
-{\r
- int i;\r
- if (!is_tripped)\r
- return;\r
- is_tripped = 0;\r
- for (i = 1; i < NSIG; ++i) {\r
- Handlers[i].tripped = 0;\r
- }\r
-}\r
-\r
-void\r
-PyOS_AfterFork(void)\r
-{\r
- /* Clear the signal flags after forking so that they aren't handled\r
- * in both processes if they came in just before the fork() but before\r
- * the interpreter had an opportunity to call the handlers. issue9535. */\r
- _clear_pending_signals();\r
-#ifdef WITH_THREAD\r
- /* PyThread_ReInitTLS() must be called early, to make sure that the TLS API\r
- * can be called safely. */\r
- PyThread_ReInitTLS();\r
- PyEval_ReInitThreads();\r
- main_thread = PyThread_get_thread_ident();\r
- main_pid = getpid();\r
- _PyImport_ReInitLock();\r
-#endif\r
-}\r