Issue #20182: converted the signal module to use Argument Clinic

This commit is contained in:
Tal Einat 2015-05-16 14:14:49 +03:00
parent 97fceee3b9
commit c7027b7904
3 changed files with 684 additions and 221 deletions

View File

@ -219,21 +219,21 @@ The :mod:`signal` module defines the following functions:
: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 <signals-and-threads>`. 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 <signals-and-threads>`. 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

View File

@ -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]*/

View File

@ -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 @@ signal_handler(int sig_num)
#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 @@ signal_pause(PyObject *self)
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 @@ signal_signal(PyObject *self, PyObject *args)
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 @@ signal_getsignal(PyObject *self, PyObject *args)
}
}
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
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 @@ PySignal_SetWakeupFd(int fd)
#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 @@ sigset_to_set(sigset_t mask)
#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 @@ signal_pthread_sigmask(PyObject *self, PyObject *args)
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 @@ signal_sigpending(PyObject *self)
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 @@ signal_sigwait(PyObject *self, PyObject *args)
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 @@ fill_siginfo(siginfo_t *si)
#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 @@ signal_sigwaitinfo(PyObject *self, PyObject *args)
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 @@ signal_sigtimedwait(PyObject *self, PyObject *args)
return NULL;
}
if (iterable_to_sigset(signals, &set))
if (iterable_to_sigset(sigset, &set))
return NULL;
deadline = _PyTime_GetMonotonicClock() + timeout;
@ -1019,26 +1081,28 @@ signal_sigtimedwait(PyObject *self, PyObject *args)
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 @@ signal_pthread_kill(PyObject *self, PyObject *args)
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 */
};