Skip to content

Commit a45a99b

Browse files
authored
[2.7] bpo-30807: signal.setitimer() may disable the timer by mistake (GH-2493) (#2499)
* bpo-30807: signal.setitimer() may disable the timer by mistake * Add NEWS blurb. (cherry picked from commit 729780a)
1 parent 12536bd commit a45a99b

File tree

3 files changed

+20
-0
lines changed

3 files changed

+20
-0
lines changed

‎Lib/test/test_signal.py‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,16 @@ def test_itimer_prof(self):
490490
# and the handler should have been called
491491
self.assertEqual(self.hndl_called, True)
492492

493+
def test_setitimer_tiny(self):
494+
# bpo-30807: C setitimer() takes a microsecond-resolution interval.
495+
# Check that float -> timeval conversion doesn't round
496+
# the interval down to zero, which would disable the timer.
497+
self.itimer = signal.ITIMER_REAL
498+
signal.setitimer(self.itimer, 1e-6)
499+
time.sleep(1)
500+
self.assertEqual(self.hndl_called, True)
501+
502+
493503
def test_main():
494504
test_support.run_unittest(BasicSignalTests, InterProcessSignalTests,
495505
WakeupFDTests, WakeupSignalTests,
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
signal.setitimer() may disable the timer when passed a tiny value.
2+
3+
Tiny values (such as 1e-6) are valid non-zero values for setitimer(), which
4+
is specified as taking microsecond-resolution intervals. However, on some
5+
platform, our conversion routine could convert 1e-6 into a zero interval,
6+
therefore disabling the timer instead of (re-)scheduling it.

‎Modules/signalmodule.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ timeval_from_double(double d, struct timeval *tv)
111111
{
112112
tv->tv_sec = floor(d);
113113
tv->tv_usec = fmod(d, 1.0) * 1000000.0;
114+
/* Don't disable the timer if the computation above rounds down to zero. */
115+
if (d > 0.0 && tv->tv_sec == 0 && tv->tv_usec == 0) {
116+
tv->tv_usec = 1;
117+
}
114118
}
115119

116120
Py_LOCAL_INLINE(double)

0 commit comments

Comments
 (0)