mirror of
https://github.com/python/cpython.git
synced 2025-12-21 08:01:36 +00:00
bpo-30807: signal.setitimer() now uses _PyTime API (GH-3865)
The _PyTime API handles detects overflow and is well tested. Document that the signal will only be sent once if internal is equal to zero.
This commit is contained in:
parent
a505ecdc50
commit
ef611c96ea
3 changed files with 35 additions and 24 deletions
|
|
@ -273,13 +273,14 @@ The :mod:`signal` module defines the following functions:
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
|
||||||
.. function:: setitimer(which, seconds[, interval])
|
.. function:: setitimer(which, seconds, interval=0.0)
|
||||||
|
|
||||||
Sets given interval timer (one of :const:`signal.ITIMER_REAL`,
|
Sets given interval timer (one of :const:`signal.ITIMER_REAL`,
|
||||||
:const:`signal.ITIMER_VIRTUAL` or :const:`signal.ITIMER_PROF`) specified
|
:const:`signal.ITIMER_VIRTUAL` or :const:`signal.ITIMER_PROF`) specified
|
||||||
by *which* to fire after *seconds* (float is accepted, different from
|
by *which* to fire after *seconds* (float is accepted, different from
|
||||||
:func:`alarm`) and after that every *interval* seconds. The interval
|
:func:`alarm`) and after that every *interval* seconds (if *interval*
|
||||||
timer specified by *which* can be cleared by setting seconds to zero.
|
is non-zero). The interval timer specified by *which* can be cleared by
|
||||||
|
setting *seconds* to zero.
|
||||||
|
|
||||||
When an interval timer fires, a signal is sent to the process.
|
When an interval timer fires, a signal is sent to the process.
|
||||||
The signal sent is dependent on the timer being used;
|
The signal sent is dependent on the timer being used;
|
||||||
|
|
|
||||||
|
|
@ -182,18 +182,18 @@ PyDoc_STRVAR(signal_setitimer__doc__,
|
||||||
{"setitimer", (PyCFunction)signal_setitimer, METH_FASTCALL, signal_setitimer__doc__},
|
{"setitimer", (PyCFunction)signal_setitimer, METH_FASTCALL, signal_setitimer__doc__},
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
signal_setitimer_impl(PyObject *module, int which, double seconds,
|
signal_setitimer_impl(PyObject *module, int which, PyObject *seconds,
|
||||||
double interval);
|
PyObject *interval);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
signal_setitimer(PyObject *module, PyObject **args, Py_ssize_t nargs)
|
signal_setitimer(PyObject *module, PyObject **args, Py_ssize_t nargs)
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
PyObject *return_value = NULL;
|
||||||
int which;
|
int which;
|
||||||
double seconds;
|
PyObject *seconds;
|
||||||
double interval = 0.0;
|
PyObject *interval = NULL;
|
||||||
|
|
||||||
if (!_PyArg_ParseStack(args, nargs, "id|d:setitimer",
|
if (!_PyArg_ParseStack(args, nargs, "iO|O:setitimer",
|
||||||
&which, &seconds, &interval)) {
|
&which, &seconds, &interval)) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
@ -440,4 +440,4 @@ exit:
|
||||||
#ifndef SIGNAL_PTHREAD_KILL_METHODDEF
|
#ifndef SIGNAL_PTHREAD_KILL_METHODDEF
|
||||||
#define SIGNAL_PTHREAD_KILL_METHODDEF
|
#define SIGNAL_PTHREAD_KILL_METHODDEF
|
||||||
#endif /* !defined(SIGNAL_PTHREAD_KILL_METHODDEF) */
|
#endif /* !defined(SIGNAL_PTHREAD_KILL_METHODDEF) */
|
||||||
/*[clinic end generated code: output=3f6e6298696f1b75 input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=a003d3fea9a33daa input=a9049054013a1b77]*/
|
||||||
|
|
|
||||||
|
|
@ -131,16 +131,21 @@ static HANDLE sigint_event = NULL;
|
||||||
#ifdef HAVE_GETITIMER
|
#ifdef HAVE_GETITIMER
|
||||||
static PyObject *ItimerError;
|
static PyObject *ItimerError;
|
||||||
|
|
||||||
/* auxiliary functions for setitimer/getitimer */
|
/* auxiliary functions for setitimer */
|
||||||
static void
|
static int
|
||||||
timeval_from_double(double d, struct timeval *tv)
|
timeval_from_double(PyObject *obj, struct timeval *tv)
|
||||||
{
|
{
|
||||||
tv->tv_sec = floor(d);
|
if (obj == NULL) {
|
||||||
tv->tv_usec = fmod(d, 1.0) * 1000000.0;
|
tv->tv_sec = 0;
|
||||||
/* Don't disable the timer if the computation above rounds down to zero. */
|
tv->tv_usec = 0;
|
||||||
if (d > 0.0 && tv->tv_sec == 0 && tv->tv_usec == 0) {
|
return 0;
|
||||||
tv->tv_usec = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_PyTime_t t;
|
||||||
|
if (_PyTime_FromSecondsObject(&t, obj, _PyTime_ROUND_CEILING) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return _PyTime_AsTimeval(t, tv, _PyTime_ROUND_CEILING);
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_LOCAL_INLINE(double)
|
Py_LOCAL_INLINE(double)
|
||||||
|
|
@ -677,8 +682,8 @@ PySignal_SetWakeupFd(int fd)
|
||||||
signal.setitimer
|
signal.setitimer
|
||||||
|
|
||||||
which: int
|
which: int
|
||||||
seconds: double
|
seconds: object
|
||||||
interval: double = 0.0
|
interval: object(c_default="NULL") = 0.0
|
||||||
/
|
/
|
||||||
|
|
||||||
Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL or ITIMER_PROF).
|
Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL or ITIMER_PROF).
|
||||||
|
|
@ -690,14 +695,19 @@ Returns old values as a tuple: (delay, interval).
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
signal_setitimer_impl(PyObject *module, int which, double seconds,
|
signal_setitimer_impl(PyObject *module, int which, PyObject *seconds,
|
||||||
double interval)
|
PyObject *interval)
|
||||||
/*[clinic end generated code: output=6f51da0fe0787f2c input=0d27d417cfcbd51a]*/
|
/*[clinic end generated code: output=65f9dcbddc35527b input=de43daf194e6f66f]*/
|
||||||
{
|
{
|
||||||
struct itimerval new, old;
|
struct itimerval new, old;
|
||||||
|
|
||||||
timeval_from_double(seconds, &new.it_value);
|
if (timeval_from_double(seconds, &new.it_value) < 0) {
|
||||||
timeval_from_double(interval, &new.it_interval);
|
return NULL;
|
||||||
|
}
|
||||||
|
if (timeval_from_double(interval, &new.it_interval) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue