Kaydet (Commit) c7027b79 authored tarafından Tal Einat's avatar Tal Einat

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

üst 97fceee3
...@@ -219,21 +219,21 @@ The :mod:`signal` module defines the following functions: ...@@ -219,21 +219,21 @@ The :mod:`signal` module defines the following functions:
:func:`sigpending`. :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 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 (Python or not). However, if the target thread is executing the Python
interpreter, the Python signal handlers will be :ref:`executed by the main 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 thread <signals-and-threads>`. Therefore, the only point of sending a
Python thread would be to force a running system call to fail with signal to a particular Python thread would be to force a running system call
:exc:`InterruptedError`. to fail with :exc:`InterruptedError`.
Use :func:`threading.get_ident()` or the :attr:`~threading.Thread.ident` Use :func:`threading.get_ident()` or the :attr:`~threading.Thread.ident`
attribute of :class:`threading.Thread` objects to get a suitable value attribute of :class:`threading.Thread` objects to get a suitable value
for *thread_id*. 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. 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 Availability: Unix (see the man page :manpage:`pthread_kill(3)` for further
......
/*[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]*/
...@@ -52,6 +52,13 @@ ...@@ -52,6 +52,13 @@
# endif # endif
#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 NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS
...@@ -322,25 +329,37 @@ signal_handler(int sig_num) ...@@ -322,25 +329,37 @@ signal_handler(int sig_num)
#ifdef HAVE_ALARM #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 */ /* 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 #endif
#ifdef HAVE_PAUSE #ifdef HAVE_PAUSE
/*[clinic input]
signal.pause
Wait until a signal arrives.
[clinic start generated code]*/
static PyObject * static PyObject *
signal_pause(PyObject *self) signal_pause_impl(PyModuleDef *module)
/*[clinic end generated code: output=9245704caa63bbe9 input=f03de0f875752062]*/
{ {
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
(void)pause(); (void)pause();
...@@ -351,29 +370,38 @@ signal_pause(PyObject *self) ...@@ -351,29 +370,38 @@ signal_pause(PyObject *self)
if (PyErr_CheckSignals()) if (PyErr_CheckSignals())
return NULL; return NULL;
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
PyDoc_STRVAR(pause_doc,
"pause()\n\
\n\
Wait until a signal arrives.");
#endif #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 * 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; PyObject *old_handler;
void (*func)(int); void (*func)(int);
if (!PyArg_ParseTuple(args, "iO:signal", &sig_num, &obj))
return NULL;
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
/* Validate that sig_num is one of the allowable signals */ /* Validate that signalnum is one of the allowable signals */
switch (sig_num) { switch (signalnum) {
case SIGABRT: break; case SIGABRT: break;
#ifdef SIGBREAK #ifdef SIGBREAK
/* Issue #10003: SIGBREAK is not documented as permitted, but works /* Issue #10003: SIGBREAK is not documented as permitted, but works
...@@ -397,61 +425,63 @@ signal_signal(PyObject *self, PyObject *args) ...@@ -397,61 +425,63 @@ signal_signal(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
#endif #endif
if (sig_num < 1 || sig_num >= NSIG) { if (signalnum < 1 || signalnum >= NSIG) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"signal number out of range"); "signal number out of range");
return NULL; return NULL;
} }
if (obj == IgnoreHandler) if (handler == IgnoreHandler)
func = SIG_IGN; func = SIG_IGN;
else if (obj == DefaultHandler) else if (handler == DefaultHandler)
func = SIG_DFL; func = SIG_DFL;
else if (!PyCallable_Check(obj)) { else if (!PyCallable_Check(handler)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object"); "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
return NULL; return NULL;
} }
else else
func = signal_handler; func = signal_handler;
if (PyOS_setsig(sig_num, func) == SIG_ERR) { if (PyOS_setsig(signalnum, func) == SIG_ERR) {
PyErr_SetFromErrno(PyExc_OSError); PyErr_SetFromErrno(PyExc_OSError);
return NULL; return NULL;
} }
old_handler = Handlers[sig_num].func; old_handler = Handlers[signalnum].func;
Handlers[sig_num].tripped = 0; Handlers[signalnum].tripped = 0;
Py_INCREF(obj); Py_INCREF(handler);
Handlers[sig_num].func = obj; Handlers[signalnum].func = handler;
if (old_handler != NULL) if (old_handler != NULL)
return old_handler; return old_handler;
else else
Py_RETURN_NONE; 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 * 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; PyObject *old_handler;
if (!PyArg_ParseTuple(args, "i:getsignal", &sig_num)) if (signalnum < 1 || signalnum >= NSIG) {
return NULL;
if (sig_num < 1 || sig_num >= NSIG) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"signal number out of range"); "signal number out of range");
return NULL; return NULL;
} }
old_handler = Handlers[sig_num].func; old_handler = Handlers[signalnum].func;
if (old_handler != NULL) { if (old_handler != NULL) {
Py_INCREF(old_handler); Py_INCREF(old_handler);
return old_handler; return old_handler;
...@@ -461,47 +491,41 @@ signal_getsignal(PyObject *self, PyObject *args) ...@@ -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 #ifdef HAVE_SIGINTERRUPT
PyDoc_STRVAR(siginterrupt_doc,
"siginterrupt(sig, flag) -> None\n\ /*[clinic input]
change system call restart behaviour: if flag is False, system calls\n\ signal.siginterrupt
will be restarted when interrupted by signal sig, else system calls\n\
will be interrupted."); 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 * 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; if (signalnum < 1 || signalnum >= NSIG) {
int flag;
if (!PyArg_ParseTuple(args, "ii:siginterrupt", &sig_num, &flag))
return NULL;
if (sig_num < 1 || sig_num >= NSIG) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"signal number out of range"); "signal number out of range");
return NULL; return NULL;
} }
if (siginterrupt(sig_num, flag)<0) { if (siginterrupt(signalnum, flag)<0) {
PyErr_SetFromErrno(PyExc_OSError); PyErr_SetFromErrno(PyExc_OSError);
return NULL; return NULL;
} }
Py_RETURN_NONE;
Py_INCREF(Py_None);
return Py_None;
} }
#endif #endif
static PyObject *
static PyObject*
signal_set_wakeup_fd(PyObject *self, PyObject *args) signal_set_wakeup_fd(PyObject *self, PyObject *args)
{ {
struct _Py_stat_struct status; struct _Py_stat_struct status;
...@@ -640,62 +664,69 @@ PySignal_SetWakeupFd(int fd) ...@@ -640,62 +664,69 @@ PySignal_SetWakeupFd(int fd)
#ifdef HAVE_SETITIMER #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 * 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; struct itimerval new, old;
if(!PyArg_ParseTuple(args, "id|d:setitimer", &which, &first, &interval)) timeval_from_double(seconds, &new.it_value);
return NULL;
timeval_from_double(first, &new.it_value);
timeval_from_double(interval, &new.it_interval); timeval_from_double(interval, &new.it_interval);
/* Let OS check "which" value */ /* Let OS check "which" value */
if (setitimer(which, &new, &old) != 0) { if (setitimer(which, &new, &old) != 0) {
PyErr_SetFromErrno(ItimerError); PyErr_SetFromErrno(ItimerError);
return NULL; return NULL;
} }
return itimer_retval(&old); 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 #endif
#ifdef HAVE_GETITIMER #ifdef HAVE_GETITIMER
/*[clinic input]
signal.getitimer
which: int
/
Returns current value of given itimer.
[clinic start generated code]*/
static PyObject * 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; struct itimerval old;
if (!PyArg_ParseTuple(args, "i:getitimer", &which))
return NULL;
if (getitimer(which, &old) != 0) { if (getitimer(which, &old) != 0) {
PyErr_SetFromErrno(ItimerError); PyErr_SetFromErrno(ItimerError);
return NULL; return NULL;
} }
return itimer_retval(&old); return itimer_retval(&old);
} }
PyDoc_STRVAR(getitimer_doc,
"getitimer(which)\n\
\n\
Returns current value of given itimer.");
#endif #endif
#if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGWAIT) || \ #if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGWAIT) || \
...@@ -786,21 +817,28 @@ sigset_to_set(sigset_t mask) ...@@ -786,21 +817,28 @@ sigset_to_set(sigset_t mask)
#endif #endif
#ifdef PYPTHREAD_SIGMASK #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 * 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; sigset_t newmask, previous;
PyObject *signals;
sigset_t mask, previous;
int err; int err;
if (!PyArg_ParseTuple(args, "iO:pthread_sigmask", &how, &signals)) if (iterable_to_sigset(mask, &newmask))
return NULL; return NULL;
if (iterable_to_sigset(signals, &mask)) err = pthread_sigmask(how, &newmask, &previous);
return NULL;
err = pthread_sigmask(how, &mask, &previous);
if (err != 0) { if (err != 0) {
errno = err; errno = err;
PyErr_SetFromErrno(PyExc_OSError); PyErr_SetFromErrno(PyExc_OSError);
...@@ -814,16 +852,23 @@ signal_pthread_sigmask(PyObject *self, PyObject *args) ...@@ -814,16 +852,23 @@ signal_pthread_sigmask(PyObject *self, PyObject *args)
return sigset_to_set(previous); 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 */ #endif /* #ifdef PYPTHREAD_SIGMASK */
#ifdef HAVE_SIGPENDING #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 * static PyObject *
signal_sigpending(PyObject *self) signal_sigpending_impl(PyModuleDef *module)
/*[clinic end generated code: output=bf4ced803e7e51dd input=e0036c016f874e29]*/
{ {
int err; int err;
sigset_t mask; sigset_t mask;
...@@ -833,25 +878,32 @@ signal_sigpending(PyObject *self) ...@@ -833,25 +878,32 @@ signal_sigpending(PyObject *self)
return sigset_to_set(mask); return sigset_to_set(mask);
} }
PyDoc_STRVAR(signal_sigpending_doc,
"sigpending() -> list\n\
\n\
Examine pending signals.");
#endif /* #ifdef HAVE_SIGPENDING */ #endif /* #ifdef HAVE_SIGPENDING */
#ifdef HAVE_SIGWAIT #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 * 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; sigset_t set;
int err, signum; int err, signum;
if (!PyArg_ParseTuple(args, "O:sigwait", &signals)) if (iterable_to_sigset(sigset, &set))
return NULL;
if (iterable_to_sigset(signals, &set))
return NULL; return NULL;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
...@@ -865,11 +917,8 @@ signal_sigwait(PyObject *self, PyObject *args) ...@@ -865,11 +917,8 @@ signal_sigwait(PyObject *self, PyObject *args)
return PyLong_FromLong(signum); return PyLong_FromLong(signum);
} }
PyDoc_STRVAR(signal_sigwait_doc, #endif /* #ifdef HAVE_SIGWAIT */
"sigwait(sigset) -> signum\n\
\n\
Wait a signal.");
#endif /* #ifdef HAVE_SIGPENDING */
#if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) #if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT)
static int initialized; static int initialized;
...@@ -924,19 +973,28 @@ fill_siginfo(siginfo_t *si) ...@@ -924,19 +973,28 @@ fill_siginfo(siginfo_t *si)
#endif #endif
#ifdef HAVE_SIGWAITINFO #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 * 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; sigset_t set;
siginfo_t si; siginfo_t si;
int err; int err;
int async_err = 0; int async_err = 0;
if (!PyArg_ParseTuple(args, "O:sigwaitinfo", &signals)) if (iterable_to_sigset(sigset, &set))
return NULL;
if (iterable_to_sigset(signals, &set))
return NULL; return NULL;
do { do {
...@@ -951,29 +1009,33 @@ signal_sigwaitinfo(PyObject *self, PyObject *args) ...@@ -951,29 +1009,33 @@ signal_sigwaitinfo(PyObject *self, PyObject *args)
return fill_siginfo(&si); 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 */ #endif /* #ifdef HAVE_SIGWAITINFO */
#ifdef HAVE_SIGTIMEDWAIT #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 * 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; struct timespec ts;
sigset_t set; sigset_t set;
siginfo_t si; siginfo_t si;
int res; int res;
_PyTime_t timeout, deadline, monotonic; _PyTime_t timeout, deadline, monotonic;
if (!PyArg_ParseTuple(args, "OO:sigtimedwait",
&signals, &timeout_obj))
return NULL;
if (_PyTime_FromSecondsObject(&timeout, if (_PyTime_FromSecondsObject(&timeout,
timeout_obj, _PyTime_ROUND_CEILING) < 0) timeout_obj, _PyTime_ROUND_CEILING) < 0)
return NULL; return NULL;
...@@ -983,7 +1045,7 @@ signal_sigtimedwait(PyObject *self, PyObject *args) ...@@ -983,7 +1045,7 @@ signal_sigtimedwait(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
if (iterable_to_sigset(signals, &set)) if (iterable_to_sigset(sigset, &set))
return NULL; return NULL;
deadline = _PyTime_GetMonotonicClock() + timeout; deadline = _PyTime_GetMonotonicClock() + timeout;
...@@ -1019,26 +1081,28 @@ signal_sigtimedwait(PyObject *self, PyObject *args) ...@@ -1019,26 +1081,28 @@ signal_sigtimedwait(PyObject *self, PyObject *args)
return fill_siginfo(&si); 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 */ #endif /* #ifdef HAVE_SIGTIMEDWAIT */
#if defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD) #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 * 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; int err;
if (!PyArg_ParseTuple(args, "li:pthread_kill", &tid, &signum)) err = pthread_kill((pthread_t)thread_id, signalnum);
return NULL;
err = pthread_kill((pthread_t)tid, signum);
if (err != 0) { if (err != 0) {
errno = err; errno = err;
PyErr_SetFromErrno(PyExc_OSError); PyErr_SetFromErrno(PyExc_OSError);
...@@ -1052,62 +1116,29 @@ signal_pthread_kill(PyObject *self, PyObject *args) ...@@ -1052,62 +1116,29 @@ signal_pthread_kill(PyObject *self, PyObject *args)
Py_RETURN_NONE; 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) */ #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[] = { static PyMethodDef signal_methods[] = {
#ifdef HAVE_ALARM {"default_int_handler", signal_default_int_handler, METH_VARARGS, default_int_handler_doc},
{"alarm", signal_alarm, METH_VARARGS, alarm_doc}, SIGNAL_ALARM_METHODDEF
#endif SIGNAL_SETITIMER_METHODDEF
#ifdef HAVE_SETITIMER SIGNAL_GETITIMER_METHODDEF
{"setitimer", signal_setitimer, METH_VARARGS, setitimer_doc}, SIGNAL_SIGNAL_METHODDEF
#endif SIGNAL_GETSIGNAL_METHODDEF
#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},
{"set_wakeup_fd", signal_set_wakeup_fd, METH_VARARGS, set_wakeup_fd_doc}, {"set_wakeup_fd", signal_set_wakeup_fd, METH_VARARGS, set_wakeup_fd_doc},
#ifdef HAVE_SIGINTERRUPT SIGNAL_SIGINTERRUPT_METHODDEF
{"siginterrupt", signal_siginterrupt, METH_VARARGS, siginterrupt_doc}, SIGNAL_PAUSE_METHODDEF
#endif SIGNAL_PTHREAD_KILL_METHODDEF
#ifdef HAVE_PAUSE SIGNAL_PTHREAD_SIGMASK_METHODDEF
{"pause", (PyCFunction)signal_pause, SIGNAL_SIGPENDING_METHODDEF
METH_NOARGS, pause_doc}, SIGNAL_SIGWAIT_METHODDEF
#endif SIGNAL_SIGWAITINFO_METHODDEF
{"default_int_handler", signal_default_int_handler, SIGNAL_SIGTIMEDWAIT_METHODDEF
METH_VARARGS, default_int_handler_doc}, {NULL, NULL} /* sentinel */
#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 */
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment