Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ef611c9

Browse files
authored
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.
1 parent a505ecd commit ef611c9

File tree

3 files changed

+35
-24
lines changed

3 files changed

+35
-24
lines changed

Doc/library/signal.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,13 +273,14 @@ The :mod:`signal` module defines the following functions:
273273
.. versionadded:: 3.3
274274

275275

276-
.. function:: setitimer(which, seconds[, interval])
276+
.. function:: setitimer(which, seconds, interval=0.0)
277277

278278
Sets given interval timer (one of :const:`signal.ITIMER_REAL`,
279279
:const:`signal.ITIMER_VIRTUAL` or :const:`signal.ITIMER_PROF`) specified
280280
by *which* to fire after *seconds* (float is accepted, different from
281-
:func:`alarm`) and after that every *interval* seconds. The interval
282-
timer specified by *which* can be cleared by setting seconds to zero.
281+
:func:`alarm`) and after that every *interval* seconds (if *interval*
282+
is non-zero). The interval timer specified by *which* can be cleared by
283+
setting *seconds* to zero.
283284

284285
When an interval timer fires, a signal is sent to the process.
285286
The signal sent is dependent on the timer being used;

Modules/clinic/signalmodule.c.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,18 +182,18 @@ PyDoc_STRVAR(signal_setitimer__doc__,
182182
{"setitimer", (PyCFunction)signal_setitimer, METH_FASTCALL, signal_setitimer__doc__},
183183

184184
static PyObject *
185-
signal_setitimer_impl(PyObject *module, int which, double seconds,
186-
double interval);
185+
signal_setitimer_impl(PyObject *module, int which, PyObject *seconds,
186+
PyObject *interval);
187187

188188
static PyObject *
189189
signal_setitimer(PyObject *module, PyObject **args, Py_ssize_t nargs)
190190
{
191191
PyObject *return_value = NULL;
192192
int which;
193-
double seconds;
194-
double interval = 0.0;
193+
PyObject *seconds;
194+
PyObject *interval = NULL;
195195

196-
if (!_PyArg_ParseStack(args, nargs, "id|d:setitimer",
196+
if (!_PyArg_ParseStack(args, nargs, "iO|O:setitimer",
197197
&which, &seconds, &interval)) {
198198
goto exit;
199199
}
@@ -440,4 +440,4 @@ signal_pthread_kill(PyObject *module, PyObject **args, Py_ssize_t nargs)
440440
#ifndef SIGNAL_PTHREAD_KILL_METHODDEF
441441
#define SIGNAL_PTHREAD_KILL_METHODDEF
442442
#endif /* !defined(SIGNAL_PTHREAD_KILL_METHODDEF) */
443-
/*[clinic end generated code: output=3f6e6298696f1b75 input=a9049054013a1b77]*/
443+
/*[clinic end generated code: output=a003d3fea9a33daa input=a9049054013a1b77]*/

Modules/signalmodule.c

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -131,16 +131,21 @@ static HANDLE sigint_event = NULL;
131131
#ifdef HAVE_GETITIMER
132132
static PyObject *ItimerError;
133133

134-
/* auxiliary functions for setitimer/getitimer */
135-
static void
136-
timeval_from_double(double d, struct timeval *tv)
134+
/* auxiliary functions for setitimer */
135+
static int
136+
timeval_from_double(PyObject *obj, struct timeval *tv)
137137
{
138-
tv->tv_sec = floor(d);
139-
tv->tv_usec = fmod(d, 1.0) * 1000000.0;
140-
/* Don't disable the timer if the computation above rounds down to zero. */
141-
if (d > 0.0 && tv->tv_sec == 0 && tv->tv_usec == 0) {
142-
tv->tv_usec = 1;
138+
if (obj == NULL) {
139+
tv->tv_sec = 0;
140+
tv->tv_usec = 0;
141+
return 0;
142+
}
143+
144+
_PyTime_t t;
145+
if (_PyTime_FromSecondsObject(&t, obj, _PyTime_ROUND_CEILING) < 0) {
146+
return -1;
143147
}
148+
return _PyTime_AsTimeval(t, tv, _PyTime_ROUND_CEILING);
144149
}
145150

146151
Py_LOCAL_INLINE(double)
@@ -677,8 +682,8 @@ PySignal_SetWakeupFd(int fd)
677682
signal.setitimer
678683
679684
which: int
680-
seconds: double
681-
interval: double = 0.0
685+
seconds: object
686+
interval: object(c_default="NULL") = 0.0
682687
/
683688
684689
Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL or ITIMER_PROF).
@@ -690,14 +695,19 @@ Returns old values as a tuple: (delay, interval).
690695
[clinic start generated code]*/
691696

692697
static PyObject *
693-
signal_setitimer_impl(PyObject *module, int which, double seconds,
694-
double interval)
695-
/*[clinic end generated code: output=6f51da0fe0787f2c input=0d27d417cfcbd51a]*/
698+
signal_setitimer_impl(PyObject *module, int which, PyObject *seconds,
699+
PyObject *interval)
700+
/*[clinic end generated code: output=65f9dcbddc35527b input=de43daf194e6f66f]*/
696701
{
697702
struct itimerval new, old;
698703

699-
timeval_from_double(seconds, &new.it_value);
700-
timeval_from_double(interval, &new.it_interval);
704+
if (timeval_from_double(seconds, &new.it_value) < 0) {
705+
return NULL;
706+
}
707+
if (timeval_from_double(interval, &new.it_interval) < 0) {
708+
return NULL;
709+
}
710+
701711
/* Let OS check "which" value */
702712
if (setitimer(which, &new, &old) != 0) {
703713
PyErr_SetFromErrno(ItimerError);

0 commit comments

Comments
 (0)