diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -219,21 +219,21 @@ :func:`sigpending`. -.. function:: pthread_kill(thread_id, signum) +.. function:: pthread_kill(thread_id, signalnum) - Send the signal *signum* to the thread *thread_id*, another thread in the + Send the signal *signalnum* to the thread *thread_id*, another thread in the same process as the caller. The target thread can be executing any code (Python or not). However, if the target thread is executing the Python interpreter, the Python signal handlers will be :ref:`executed by the main - thread `. Therefore, the only point of sending a signal to a particular - Python thread would be to force a running system call to fail with - :exc:`InterruptedError`. + thread `. Therefore, the only point of sending a + signal to a particular Python thread would be to force a running system call + to fail with :exc:`InterruptedError`. Use :func:`threading.get_ident()` or the :attr:`~threading.Thread.ident` attribute of :class:`threading.Thread` objects to get a suitable value for *thread_id*. - If *signum* is 0, then no signal is sent, but error checking is still + If *signalnum* is 0, then no signal is sent, but error checking is still performed; this can be used to check if the target thread is still running. Availability: Unix (see the man page :manpage:`pthread_kill(3)` for further diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h new file mode 100644 --- /dev/null +++ b/Modules/clinic/signalmodule.c.h @@ -0,0 +1,432 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(HAVE_ALARM) + +PyDoc_STRVAR(signal_alarm__doc__, +"alarm($module, seconds, /)\n" +"--\n" +"\n" +"Arrange for SIGALRM to arrive after the given number of seconds."); + +#define SIGNAL_ALARM_METHODDEF \ + {"alarm", (PyCFunction)signal_alarm, METH_O, signal_alarm__doc__}, + +static long +signal_alarm_impl(PyModuleDef *module, int seconds); + +static PyObject * +signal_alarm(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int seconds; + long _return_value; + + if (!PyArg_Parse(arg, "i:alarm", &seconds)) + goto exit; + _return_value = signal_alarm_impl(module, seconds); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_ALARM) */ + +#if defined(HAVE_PAUSE) + +PyDoc_STRVAR(signal_pause__doc__, +"pause($module, /)\n" +"--\n" +"\n" +"Wait until a signal arrives."); + +#define SIGNAL_PAUSE_METHODDEF \ + {"pause", (PyCFunction)signal_pause, METH_NOARGS, signal_pause__doc__}, + +static PyObject * +signal_pause_impl(PyModuleDef *module); + +static PyObject * +signal_pause(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return signal_pause_impl(module); +} + +#endif /* defined(HAVE_PAUSE) */ + +PyDoc_STRVAR(signal_signal__doc__, +"signal($module, signalnum, handler, /)\n" +"--\n" +"\n" +"Set the action for the given signal.\n" +"\n" +"The action can be SIG_DFL, SIG_IGN, or a callable Python object.\n" +"The previous action is returned. See getsignal() for possible return values.\n" +"\n" +"*** IMPORTANT NOTICE ***\n" +"A signal handler function is called with two arguments:\n" +"the first is the signal number, the second is the interrupted stack frame."); + +#define SIGNAL_SIGNAL_METHODDEF \ + {"signal", (PyCFunction)signal_signal, METH_VARARGS, signal_signal__doc__}, + +static PyObject * +signal_signal_impl(PyModuleDef *module, int signalnum, PyObject *handler); + +static PyObject * +signal_signal(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int signalnum; + PyObject *handler; + + if (!PyArg_ParseTuple(args, "iO:signal", + &signalnum, &handler)) + goto exit; + return_value = signal_signal_impl(module, signalnum, handler); + +exit: + return return_value; +} + +PyDoc_STRVAR(signal_getsignal__doc__, +"getsignal($module, signalnum, /)\n" +"--\n" +"\n" +"Return the current action for the given signal.\n" +"\n" +"The return value can be:\n" +" SIG_IGN -- if the signal is being ignored\n" +" SIG_DFL -- if the default action for the signal is in effect\n" +" None -- if an unknown handler is in effect\n" +" anything else -- the callable Python object used as a handler"); + +#define SIGNAL_GETSIGNAL_METHODDEF \ + {"getsignal", (PyCFunction)signal_getsignal, METH_O, signal_getsignal__doc__}, + +static PyObject * +signal_getsignal_impl(PyModuleDef *module, int signalnum); + +static PyObject * +signal_getsignal(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int signalnum; + + if (!PyArg_Parse(arg, "i:getsignal", &signalnum)) + goto exit; + return_value = signal_getsignal_impl(module, signalnum); + +exit: + return return_value; +} + +#if defined(HAVE_SIGINTERRUPT) + +PyDoc_STRVAR(signal_siginterrupt__doc__, +"siginterrupt($module, signalnum, flag, /)\n" +"--\n" +"\n" +"Change system call restart behaviour.\n" +"\n" +"If flag is False, system calls will be restarted when interrupted by\n" +"signal sig, else system calls will be interrupted."); + +#define SIGNAL_SIGINTERRUPT_METHODDEF \ + {"siginterrupt", (PyCFunction)signal_siginterrupt, METH_VARARGS, signal_siginterrupt__doc__}, + +static PyObject * +signal_siginterrupt_impl(PyModuleDef *module, int signalnum, int flag); + +static PyObject * +signal_siginterrupt(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int signalnum; + int flag; + + if (!PyArg_ParseTuple(args, "ii:siginterrupt", + &signalnum, &flag)) + goto exit; + return_value = signal_siginterrupt_impl(module, signalnum, flag); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SIGINTERRUPT) */ + +#if defined(HAVE_SETITIMER) + +PyDoc_STRVAR(signal_setitimer__doc__, +"setitimer($module, which, seconds, interval=0.0, /)\n" +"--\n" +"\n" +"Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL or ITIMER_PROF).\n" +"\n" +"The timer will fire after value seconds and after that every interval seconds.\n" +"The itimer can be cleared by setting seconds to zero.\n" +"\n" +"Returns old values as a tuple: (delay, interval)."); + +#define SIGNAL_SETITIMER_METHODDEF \ + {"setitimer", (PyCFunction)signal_setitimer, METH_VARARGS, signal_setitimer__doc__}, + +static PyObject * +signal_setitimer_impl(PyModuleDef *module, int which, double seconds, + double interval); + +static PyObject * +signal_setitimer(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int which; + double seconds; + double interval = 0.0; + + if (!PyArg_ParseTuple(args, "id|d:setitimer", + &which, &seconds, &interval)) + goto exit; + return_value = signal_setitimer_impl(module, which, seconds, interval); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETITIMER) */ + +#if defined(HAVE_GETITIMER) + +PyDoc_STRVAR(signal_getitimer__doc__, +"getitimer($module, which, /)\n" +"--\n" +"\n" +"Returns current value of given itimer."); + +#define SIGNAL_GETITIMER_METHODDEF \ + {"getitimer", (PyCFunction)signal_getitimer, METH_O, signal_getitimer__doc__}, + +static PyObject * +signal_getitimer_impl(PyModuleDef *module, int which); + +static PyObject * +signal_getitimer(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int which; + + if (!PyArg_Parse(arg, "i:getitimer", &which)) + goto exit; + return_value = signal_getitimer_impl(module, which); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETITIMER) */ + +#if defined(PYPTHREAD_SIGMASK) + +PyDoc_STRVAR(signal_pthread_sigmask__doc__, +"pthread_sigmask($module, how, mask, /)\n" +"--\n" +"\n" +"Fetch and/or change the signal mask of the calling thread."); + +#define SIGNAL_PTHREAD_SIGMASK_METHODDEF \ + {"pthread_sigmask", (PyCFunction)signal_pthread_sigmask, METH_VARARGS, signal_pthread_sigmask__doc__}, + +static PyObject * +signal_pthread_sigmask_impl(PyModuleDef *module, int how, PyObject *mask); + +static PyObject * +signal_pthread_sigmask(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int how; + PyObject *mask; + + if (!PyArg_ParseTuple(args, "iO:pthread_sigmask", + &how, &mask)) + goto exit; + return_value = signal_pthread_sigmask_impl(module, how, mask); + +exit: + return return_value; +} + +#endif /* defined(PYPTHREAD_SIGMASK) */ + +#if defined(HAVE_SIGPENDING) + +PyDoc_STRVAR(signal_sigpending__doc__, +"sigpending($module, /)\n" +"--\n" +"\n" +"Examine pending signals.\n" +"\n" +"Returns a set of signal numbers that are pending for delivery to\n" +"the calling thread."); + +#define SIGNAL_SIGPENDING_METHODDEF \ + {"sigpending", (PyCFunction)signal_sigpending, METH_NOARGS, signal_sigpending__doc__}, + +static PyObject * +signal_sigpending_impl(PyModuleDef *module); + +static PyObject * +signal_sigpending(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return signal_sigpending_impl(module); +} + +#endif /* defined(HAVE_SIGPENDING) */ + +#if defined(HAVE_SIGWAIT) + +PyDoc_STRVAR(signal_sigwait__doc__, +"sigwait($module, sigset, /)\n" +"--\n" +"\n" +"Wait for a signal.\n" +"\n" +"Suspend execution of the calling thread until the delivery of one of the\n" +"signals specified in the signal set sigset. The function accepts the signal\n" +"and returns the signal number."); + +#define SIGNAL_SIGWAIT_METHODDEF \ + {"sigwait", (PyCFunction)signal_sigwait, METH_O, signal_sigwait__doc__}, + +#endif /* defined(HAVE_SIGWAIT) */ + +#if defined(HAVE_SIGWAITINFO) + +PyDoc_STRVAR(signal_sigwaitinfo__doc__, +"sigwaitinfo($module, sigset, /)\n" +"--\n" +"\n" +"Wait synchronously until one of the signals in *sigset* is delivered.\n" +"\n" +"Returns a struct_siginfo containing information about the signal."); + +#define SIGNAL_SIGWAITINFO_METHODDEF \ + {"sigwaitinfo", (PyCFunction)signal_sigwaitinfo, METH_O, signal_sigwaitinfo__doc__}, + +#endif /* defined(HAVE_SIGWAITINFO) */ + +#if defined(HAVE_SIGTIMEDWAIT) + +PyDoc_STRVAR(signal_sigtimedwait__doc__, +"sigtimedwait($module, sigset, timeout, /)\n" +"--\n" +"\n" +"Like sigwaitinfo(), but with a timeout.\n" +"\n" +"The timeout is specified in seconds, with floating point numbers allowed."); + +#define SIGNAL_SIGTIMEDWAIT_METHODDEF \ + {"sigtimedwait", (PyCFunction)signal_sigtimedwait, METH_VARARGS, signal_sigtimedwait__doc__}, + +static PyObject * +signal_sigtimedwait_impl(PyModuleDef *module, PyObject *sigset, + PyObject *timeout); + +static PyObject * +signal_sigtimedwait(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *sigset; + PyObject *timeout; + + if (!PyArg_UnpackTuple(args, "sigtimedwait", + 2, 2, + &sigset, &timeout)) + goto exit; + return_value = signal_sigtimedwait_impl(module, sigset, timeout); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SIGTIMEDWAIT) */ + +#if (defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD)) + +PyDoc_STRVAR(signal_pthread_kill__doc__, +"pthread_kill($module, thread_id, signalnum, /)\n" +"--\n" +"\n" +"Send a signal to a thread."); + +#define SIGNAL_PTHREAD_KILL_METHODDEF \ + {"pthread_kill", (PyCFunction)signal_pthread_kill, METH_VARARGS, signal_pthread_kill__doc__}, + +static PyObject * +signal_pthread_kill_impl(PyModuleDef *module, long thread_id, int signalnum); + +static PyObject * +signal_pthread_kill(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + long thread_id; + int signalnum; + + if (!PyArg_ParseTuple(args, "li:pthread_kill", + &thread_id, &signalnum)) + goto exit; + return_value = signal_pthread_kill_impl(module, thread_id, signalnum); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD)) */ + +#ifndef SIGNAL_ALARM_METHODDEF + #define SIGNAL_ALARM_METHODDEF +#endif /* !defined(SIGNAL_ALARM_METHODDEF) */ + +#ifndef SIGNAL_PAUSE_METHODDEF + #define SIGNAL_PAUSE_METHODDEF +#endif /* !defined(SIGNAL_PAUSE_METHODDEF) */ + +#ifndef SIGNAL_SIGINTERRUPT_METHODDEF + #define SIGNAL_SIGINTERRUPT_METHODDEF +#endif /* !defined(SIGNAL_SIGINTERRUPT_METHODDEF) */ + +#ifndef SIGNAL_SETITIMER_METHODDEF + #define SIGNAL_SETITIMER_METHODDEF +#endif /* !defined(SIGNAL_SETITIMER_METHODDEF) */ + +#ifndef SIGNAL_GETITIMER_METHODDEF + #define SIGNAL_GETITIMER_METHODDEF +#endif /* !defined(SIGNAL_GETITIMER_METHODDEF) */ + +#ifndef SIGNAL_PTHREAD_SIGMASK_METHODDEF + #define SIGNAL_PTHREAD_SIGMASK_METHODDEF +#endif /* !defined(SIGNAL_PTHREAD_SIGMASK_METHODDEF) */ + +#ifndef SIGNAL_SIGPENDING_METHODDEF + #define SIGNAL_SIGPENDING_METHODDEF +#endif /* !defined(SIGNAL_SIGPENDING_METHODDEF) */ + +#ifndef SIGNAL_SIGWAIT_METHODDEF + #define SIGNAL_SIGWAIT_METHODDEF +#endif /* !defined(SIGNAL_SIGWAIT_METHODDEF) */ + +#ifndef SIGNAL_SIGWAITINFO_METHODDEF + #define SIGNAL_SIGWAITINFO_METHODDEF +#endif /* !defined(SIGNAL_SIGWAITINFO_METHODDEF) */ + +#ifndef SIGNAL_SIGTIMEDWAIT_METHODDEF + #define SIGNAL_SIGTIMEDWAIT_METHODDEF +#endif /* !defined(SIGNAL_SIGTIMEDWAIT_METHODDEF) */ + +#ifndef SIGNAL_PTHREAD_KILL_METHODDEF + #define SIGNAL_PTHREAD_KILL_METHODDEF +#endif /* !defined(SIGNAL_PTHREAD_KILL_METHODDEF) */ +/*[clinic end generated code: output=65ca7b83632eda99 input=a9049054013a1b77]*/ diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -52,6 +52,13 @@ # endif #endif +#include "clinic/signalmodule.c.h" + +/*[clinic input] +module signal +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0301a3bde5fe9d3]*/ + /* NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS @@ -322,25 +329,37 @@ #ifdef HAVE_ALARM -static PyObject * -signal_alarm(PyObject *self, PyObject *args) + +/*[clinic input] +signal.alarm -> long + + seconds: int + / + +Arrange for SIGALRM to arrive after the given number of seconds. +[clinic start generated code]*/ + +static long +signal_alarm_impl(PyModuleDef *module, int seconds) +/*[clinic end generated code: output=f5f9badaab25d3e7 input=0d5e97e0e6f39e86]*/ { - int t; - if (!PyArg_ParseTuple(args, "i:alarm", &t)) - return NULL; /* alarm() returns the number of seconds remaining */ - return PyLong_FromLong((long)alarm(t)); + return (long)alarm(seconds); } -PyDoc_STRVAR(alarm_doc, -"alarm(seconds)\n\ -\n\ -Arrange for SIGALRM to arrive after the given number of seconds."); #endif #ifdef HAVE_PAUSE + +/*[clinic input] +signal.pause + +Wait until a signal arrives. +[clinic start generated code]*/ + static PyObject * -signal_pause(PyObject *self) +signal_pause_impl(PyModuleDef *module) +/*[clinic end generated code: output=9245704caa63bbe9 input=f03de0f875752062]*/ { Py_BEGIN_ALLOW_THREADS (void)pause(); @@ -351,29 +370,38 @@ if (PyErr_CheckSignals()) return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } -PyDoc_STRVAR(pause_doc, -"pause()\n\ -\n\ -Wait until a signal arrives."); #endif +/*[clinic input] +signal.signal + + signalnum: int + handler: object + / + +Set the action for the given signal. + +The action can be SIG_DFL, SIG_IGN, or a callable Python object. +The previous action is returned. See getsignal() for possible return values. + +*** IMPORTANT NOTICE *** +A signal handler function is called with two arguments: +the first is the signal number, the second is the interrupted stack frame. +[clinic start generated code]*/ + static PyObject * -signal_signal(PyObject *self, PyObject *args) +signal_signal_impl(PyModuleDef *module, int signalnum, PyObject *handler) +/*[clinic end generated code: output=622d7d0beebea546 input=deee84af5fa0432c]*/ { - PyObject *obj; - int sig_num; PyObject *old_handler; void (*func)(int); - if (!PyArg_ParseTuple(args, "iO:signal", &sig_num, &obj)) - return NULL; #ifdef MS_WINDOWS - /* Validate that sig_num is one of the allowable signals */ - switch (sig_num) { + /* Validate that signalnum is one of the allowable signals */ + switch (signalnum) { case SIGABRT: break; #ifdef SIGBREAK /* Issue #10003: SIGBREAK is not documented as permitted, but works @@ -397,61 +425,63 @@ return NULL; } #endif - if (sig_num < 1 || sig_num >= NSIG) { + if (signalnum < 1 || signalnum >= NSIG) { PyErr_SetString(PyExc_ValueError, "signal number out of range"); return NULL; } - if (obj == IgnoreHandler) + if (handler == IgnoreHandler) func = SIG_IGN; - else if (obj == DefaultHandler) + else if (handler == DefaultHandler) func = SIG_DFL; - else if (!PyCallable_Check(obj)) { + else if (!PyCallable_Check(handler)) { PyErr_SetString(PyExc_TypeError, "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object"); return NULL; } else func = signal_handler; - if (PyOS_setsig(sig_num, func) == SIG_ERR) { + if (PyOS_setsig(signalnum, func) == SIG_ERR) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } - old_handler = Handlers[sig_num].func; - Handlers[sig_num].tripped = 0; - Py_INCREF(obj); - Handlers[sig_num].func = obj; + old_handler = Handlers[signalnum].func; + Handlers[signalnum].tripped = 0; + Py_INCREF(handler); + Handlers[signalnum].func = handler; if (old_handler != NULL) return old_handler; else Py_RETURN_NONE; } -PyDoc_STRVAR(signal_doc, -"signal(sig, action) -> action\n\ -\n\ -Set the action for the given signal. The action can be SIG_DFL,\n\ -SIG_IGN, or a callable Python object. The previous action is\n\ -returned. See getsignal() for possible return values.\n\ -\n\ -*** IMPORTANT NOTICE ***\n\ -A signal handler function is called with two arguments:\n\ -the first is the signal number, the second is the interrupted stack frame."); +/*[clinic input] +signal.getsignal + + signalnum: int + / + +Return the current action for the given signal. + +The return value can be: + SIG_IGN -- if the signal is being ignored + SIG_DFL -- if the default action for the signal is in effect + None -- if an unknown handler is in effect + anything else -- the callable Python object used as a handler +[clinic start generated code]*/ static PyObject * -signal_getsignal(PyObject *self, PyObject *args) +signal_getsignal_impl(PyModuleDef *module, int signalnum) +/*[clinic end generated code: output=d50ec355757e360c input=ac23a00f19dfa509]*/ { - int sig_num; PyObject *old_handler; - if (!PyArg_ParseTuple(args, "i:getsignal", &sig_num)) - return NULL; - if (sig_num < 1 || sig_num >= NSIG) { + if (signalnum < 1 || signalnum >= NSIG) { PyErr_SetString(PyExc_ValueError, "signal number out of range"); return NULL; } - old_handler = Handlers[sig_num].func; + old_handler = Handlers[signalnum].func; if (old_handler != NULL) { Py_INCREF(old_handler); return old_handler; @@ -461,47 +491,41 @@ } } -PyDoc_STRVAR(getsignal_doc, -"getsignal(sig) -> action\n\ -\n\ -Return the current action for the given signal. The return value can be:\n\ -SIG_IGN -- if the signal is being ignored\n\ -SIG_DFL -- if the default action for the signal is in effect\n\ -None -- if an unknown handler is in effect\n\ -anything else -- the callable Python object used as a handler"); +#ifdef HAVE_SIGINTERRUPT -#ifdef HAVE_SIGINTERRUPT -PyDoc_STRVAR(siginterrupt_doc, -"siginterrupt(sig, flag) -> None\n\ -change system call restart behaviour: if flag is False, system calls\n\ -will be restarted when interrupted by signal sig, else system calls\n\ -will be interrupted."); +/*[clinic input] +signal.siginterrupt + + signalnum: int + flag: int + / + +Change system call restart behaviour. + +If flag is False, system calls will be restarted when interrupted by +signal sig, else system calls will be interrupted. +[clinic start generated code]*/ static PyObject * -signal_siginterrupt(PyObject *self, PyObject *args) +signal_siginterrupt_impl(PyModuleDef *module, int signalnum, int flag) +/*[clinic end generated code: output=5dcf8b031b0e8044 input=4160acacca3e2099]*/ { - int sig_num; - int flag; - - if (!PyArg_ParseTuple(args, "ii:siginterrupt", &sig_num, &flag)) - return NULL; - if (sig_num < 1 || sig_num >= NSIG) { + if (signalnum < 1 || signalnum >= NSIG) { PyErr_SetString(PyExc_ValueError, "signal number out of range"); return NULL; } - if (siginterrupt(sig_num, flag)<0) { + if (siginterrupt(signalnum, flag)<0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } - - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } #endif -static PyObject * + +static PyObject* signal_set_wakeup_fd(PyObject *self, PyObject *args) { struct _Py_stat_struct status; @@ -640,62 +664,69 @@ #ifdef HAVE_SETITIMER + +/*[clinic input] +signal.setitimer + + which: int + seconds: double + interval: double = 0.0 + / + +Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL or ITIMER_PROF). + +The timer will fire after value seconds and after that every interval seconds. +The itimer can be cleared by setting seconds to zero. + +Returns old values as a tuple: (delay, interval). +[clinic start generated code]*/ + static PyObject * -signal_setitimer(PyObject *self, PyObject *args) +signal_setitimer_impl(PyModuleDef *module, int which, double seconds, + double interval) +/*[clinic end generated code: output=9a9227a27bd05988 input=0d27d417cfcbd51a]*/ { - double first; - double interval = 0; - int which; struct itimerval new, old; - if(!PyArg_ParseTuple(args, "id|d:setitimer", &which, &first, &interval)) - return NULL; - - timeval_from_double(first, &new.it_value); + timeval_from_double(seconds, &new.it_value); timeval_from_double(interval, &new.it_interval); /* Let OS check "which" value */ if (setitimer(which, &new, &old) != 0) { - PyErr_SetFromErrno(ItimerError); - return NULL; + PyErr_SetFromErrno(ItimerError); + return NULL; } return itimer_retval(&old); } -PyDoc_STRVAR(setitimer_doc, -"setitimer(which, seconds[, interval])\n\ -\n\ -Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL\n\ -or ITIMER_PROF) to fire after value seconds and after\n\ -that every interval seconds.\n\ -The itimer can be cleared by setting seconds to zero.\n\ -\n\ -Returns old values as a tuple: (delay, interval)."); #endif #ifdef HAVE_GETITIMER + +/*[clinic input] +signal.getitimer + + which: int + / + +Returns current value of given itimer. +[clinic start generated code]*/ + static PyObject * -signal_getitimer(PyObject *self, PyObject *args) +signal_getitimer_impl(PyModuleDef *module, int which) +/*[clinic end generated code: output=d1349ab18aadc569 input=f7d21d38f3490627]*/ { - int which; struct itimerval old; - if (!PyArg_ParseTuple(args, "i:getitimer", &which)) - return NULL; - if (getitimer(which, &old) != 0) { - PyErr_SetFromErrno(ItimerError); - return NULL; + PyErr_SetFromErrno(ItimerError); + return NULL; } return itimer_retval(&old); } -PyDoc_STRVAR(getitimer_doc, -"getitimer(which)\n\ -\n\ -Returns current value of given itimer."); #endif #if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGWAIT) || \ @@ -786,21 +817,28 @@ #endif #ifdef PYPTHREAD_SIGMASK + +/*[clinic input] +signal.pthread_sigmask + + how: int + mask: object + / + +Fetch and/or change the signal mask of the calling thread. +[clinic start generated code]*/ + static PyObject * -signal_pthread_sigmask(PyObject *self, PyObject *args) +signal_pthread_sigmask_impl(PyModuleDef *module, int how, PyObject *mask) +/*[clinic end generated code: output=b043a9f0eeb1e075 input=f3b7d7a61b7b8283]*/ { - int how; - PyObject *signals; - sigset_t mask, previous; + sigset_t newmask, previous; int err; - if (!PyArg_ParseTuple(args, "iO:pthread_sigmask", &how, &signals)) + if (iterable_to_sigset(mask, &newmask)) return NULL; - if (iterable_to_sigset(signals, &mask)) - return NULL; - - err = pthread_sigmask(how, &mask, &previous); + err = pthread_sigmask(how, &newmask, &previous); if (err != 0) { errno = err; PyErr_SetFromErrno(PyExc_OSError); @@ -814,16 +852,23 @@ return sigset_to_set(previous); } -PyDoc_STRVAR(signal_pthread_sigmask_doc, -"pthread_sigmask(how, mask) -> old mask\n\ -\n\ -Fetch and/or change the signal mask of the calling thread."); #endif /* #ifdef PYPTHREAD_SIGMASK */ #ifdef HAVE_SIGPENDING + +/*[clinic input] +signal.sigpending + +Examine pending signals. + +Returns a set of signal numbers that are pending for delivery to +the calling thread. +[clinic start generated code]*/ + static PyObject * -signal_sigpending(PyObject *self) +signal_sigpending_impl(PyModuleDef *module) +/*[clinic end generated code: output=bf4ced803e7e51dd input=e0036c016f874e29]*/ { int err; sigset_t mask; @@ -833,25 +878,32 @@ return sigset_to_set(mask); } -PyDoc_STRVAR(signal_sigpending_doc, -"sigpending() -> list\n\ -\n\ -Examine pending signals."); #endif /* #ifdef HAVE_SIGPENDING */ #ifdef HAVE_SIGWAIT + +/*[clinic input] +signal.sigwait + + sigset: object + / + +Wait for a signal. + +Suspend execution of the calling thread until the delivery of one of the +signals specified in the signal set sigset. The function accepts the signal +and returns the signal number. +[clinic start generated code]*/ + static PyObject * -signal_sigwait(PyObject *self, PyObject *args) +signal_sigwait(PyModuleDef *module, PyObject *sigset) +/*[clinic end generated code: output=dae53048b0336a5c input=11af2d82d83c2e94]*/ { - PyObject *signals; sigset_t set; int err, signum; - if (!PyArg_ParseTuple(args, "O:sigwait", &signals)) - return NULL; - - if (iterable_to_sigset(signals, &set)) + if (iterable_to_sigset(sigset, &set)) return NULL; Py_BEGIN_ALLOW_THREADS @@ -865,11 +917,8 @@ return PyLong_FromLong(signum); } -PyDoc_STRVAR(signal_sigwait_doc, -"sigwait(sigset) -> signum\n\ -\n\ -Wait a signal."); -#endif /* #ifdef HAVE_SIGPENDING */ +#endif /* #ifdef HAVE_SIGWAIT */ + #if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) static int initialized; @@ -924,19 +973,28 @@ #endif #ifdef HAVE_SIGWAITINFO + +/*[clinic input] +signal.sigwaitinfo + + sigset: object + / + +Wait synchronously until one of the signals in *sigset* is delivered. + +Returns a struct_siginfo containing information about the signal. +[clinic start generated code]*/ + static PyObject * -signal_sigwaitinfo(PyObject *self, PyObject *args) +signal_sigwaitinfo(PyModuleDef *module, PyObject *sigset) +/*[clinic end generated code: output=0bb53b07e5e926b5 input=f3779a74a991e171]*/ { - PyObject *signals; sigset_t set; siginfo_t si; int err; int async_err = 0; - if (!PyArg_ParseTuple(args, "O:sigwaitinfo", &signals)) - return NULL; - - if (iterable_to_sigset(signals, &set)) + if (iterable_to_sigset(sigset, &set)) return NULL; do { @@ -951,29 +1009,33 @@ return fill_siginfo(&si); } -PyDoc_STRVAR(signal_sigwaitinfo_doc, -"sigwaitinfo(sigset) -> struct_siginfo\n\ -\n\ -Wait synchronously for a signal until one of the signals in *sigset* is\n\ -delivered.\n\ -Returns a struct_siginfo containing information about the signal."); #endif /* #ifdef HAVE_SIGWAITINFO */ #ifdef HAVE_SIGTIMEDWAIT + +/*[clinic input] +signal.sigtimedwait + + sigset: object + timeout: object + / + +Like sigwaitinfo(), but with a timeout. + +The timeout is specified in seconds, with floating point numbers allowed. +[clinic start generated code]*/ + static PyObject * -signal_sigtimedwait(PyObject *self, PyObject *args) +signal_sigtimedwait_impl(PyModuleDef *module, PyObject *sigset, + PyObject *timeout) +/*[clinic end generated code: output=e6e049f2bddea688 input=036bbab9b15cb8de]*/ { - PyObject *signals, *timeout_obj; struct timespec ts; sigset_t set; siginfo_t si; int res; _PyTime_t timeout, deadline, monotonic; - if (!PyArg_ParseTuple(args, "OO:sigtimedwait", - &signals, &timeout_obj)) - return NULL; - if (_PyTime_FromSecondsObject(&timeout, timeout_obj, _PyTime_ROUND_CEILING) < 0) return NULL; @@ -983,7 +1045,7 @@ return NULL; } - if (iterable_to_sigset(signals, &set)) + if (iterable_to_sigset(sigset, &set)) return NULL; deadline = _PyTime_GetMonotonicClock() + timeout; @@ -1019,26 +1081,28 @@ return fill_siginfo(&si); } -PyDoc_STRVAR(signal_sigtimedwait_doc, -"sigtimedwait(sigset, (timeout_sec, timeout_nsec)) -> struct_siginfo\n\ -\n\ -Like sigwaitinfo(), but with a timeout specified as a tuple of (seconds,\n\ -nanoseconds)."); #endif /* #ifdef HAVE_SIGTIMEDWAIT */ #if defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD) + +/*[clinic input] +signal.pthread_kill + + thread_id: long + signalnum: int + / + +Send a signal to a thread. +[clinic start generated code]*/ + static PyObject * -signal_pthread_kill(PyObject *self, PyObject *args) +signal_pthread_kill_impl(PyModuleDef *module, long thread_id, int signalnum) +/*[clinic end generated code: output=35aed2713c756d7a input=77ed6a3b6f2a8122]*/ { - long tid; - int signum; int err; - if (!PyArg_ParseTuple(args, "li:pthread_kill", &tid, &signum)) - return NULL; - - err = pthread_kill((pthread_t)tid, signum); + err = pthread_kill((pthread_t)thread_id, signalnum); if (err != 0) { errno = err; PyErr_SetFromErrno(PyExc_OSError); @@ -1052,62 +1116,29 @@ Py_RETURN_NONE; } -PyDoc_STRVAR(signal_pthread_kill_doc, -"pthread_kill(thread_id, signum)\n\ -\n\ -Send a signal to a thread."); #endif /* #if defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD) */ -/* List of functions defined in the module */ +/* List of functions defined in the module -- some of the methoddefs are + defined to nothing if the corresponding C function is not available. */ static PyMethodDef signal_methods[] = { -#ifdef HAVE_ALARM - {"alarm", signal_alarm, METH_VARARGS, alarm_doc}, -#endif -#ifdef HAVE_SETITIMER - {"setitimer", signal_setitimer, METH_VARARGS, setitimer_doc}, -#endif -#ifdef HAVE_GETITIMER - {"getitimer", signal_getitimer, METH_VARARGS, getitimer_doc}, -#endif - {"signal", signal_signal, METH_VARARGS, signal_doc}, - {"getsignal", signal_getsignal, METH_VARARGS, getsignal_doc}, + {"default_int_handler", signal_default_int_handler, METH_VARARGS, default_int_handler_doc}, + SIGNAL_ALARM_METHODDEF + SIGNAL_SETITIMER_METHODDEF + SIGNAL_GETITIMER_METHODDEF + SIGNAL_SIGNAL_METHODDEF + SIGNAL_GETSIGNAL_METHODDEF {"set_wakeup_fd", signal_set_wakeup_fd, METH_VARARGS, set_wakeup_fd_doc}, -#ifdef HAVE_SIGINTERRUPT - {"siginterrupt", signal_siginterrupt, METH_VARARGS, siginterrupt_doc}, -#endif -#ifdef HAVE_PAUSE - {"pause", (PyCFunction)signal_pause, - METH_NOARGS, pause_doc}, -#endif - {"default_int_handler", signal_default_int_handler, - METH_VARARGS, default_int_handler_doc}, -#if defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD) - {"pthread_kill", (PyCFunction)signal_pthread_kill, - METH_VARARGS, signal_pthread_kill_doc}, -#endif -#ifdef PYPTHREAD_SIGMASK - {"pthread_sigmask", (PyCFunction)signal_pthread_sigmask, - METH_VARARGS, signal_pthread_sigmask_doc}, -#endif -#ifdef HAVE_SIGPENDING - {"sigpending", (PyCFunction)signal_sigpending, - METH_NOARGS, signal_sigpending_doc}, -#endif -#ifdef HAVE_SIGWAIT - {"sigwait", (PyCFunction)signal_sigwait, - METH_VARARGS, signal_sigwait_doc}, -#endif -#ifdef HAVE_SIGWAITINFO - {"sigwaitinfo", (PyCFunction)signal_sigwaitinfo, - METH_VARARGS, signal_sigwaitinfo_doc}, -#endif -#ifdef HAVE_SIGTIMEDWAIT - {"sigtimedwait", (PyCFunction)signal_sigtimedwait, - METH_VARARGS, signal_sigtimedwait_doc}, -#endif - {NULL, NULL} /* sentinel */ + SIGNAL_SIGINTERRUPT_METHODDEF + SIGNAL_PAUSE_METHODDEF + SIGNAL_PTHREAD_KILL_METHODDEF + SIGNAL_PTHREAD_SIGMASK_METHODDEF + SIGNAL_SIGPENDING_METHODDEF + SIGNAL_SIGWAIT_METHODDEF + SIGNAL_SIGWAITINFO_METHODDEF + SIGNAL_SIGTIMEDWAIT_METHODDEF + {NULL, NULL} /* sentinel */ };