[3.5] bpo-30807: signal.setitimer() may disable the timer by mistake … · python/cpython@5741b70 (original) (raw)
3 files changed
lines changed
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -764,6 +764,15 @@ def test_itimer_prof(self): | ||
764 | 764 | # and the handler should have been called |
765 | 765 | self.assertEqual(self.hndl_called, True) |
766 | 766 | |
767 | +def test_setitimer_tiny(self): | |
768 | +# bpo-30807: C setitimer() takes a microsecond-resolution interval. | |
769 | +# Check that float -> timeval conversion doesn't round | |
770 | +# the interval down to zero, which would disable the timer. | |
771 | +self.itimer = signal.ITIMER_REAL | |
772 | +signal.setitimer(self.itimer, 1e-6) | |
773 | +time.sleep(1) | |
774 | +self.assertEqual(self.hndl_called, True) | |
775 | + | |
767 | 776 | |
768 | 777 | class PendingSignalsTests(unittest.TestCase): |
769 | 778 | """ |
Original file line number | Diff line number | Diff 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. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -139,6 +139,10 @@ timeval_from_double(double d, struct timeval *tv) | ||
139 | 139 | { |
140 | 140 | tv->tv_sec = floor(d); |
141 | 141 | tv->tv_usec = fmod(d, 1.0) * 1000000.0; |
142 | +/* Don't disable the timer if the computation above rounds down to zero. */ | |
143 | +if (d > 0.0 && tv->tv_sec == 0 && tv->tv_usec == 0) { | |
144 | +tv->tv_usec = 1; | |
145 | + } | |
142 | 146 | } |
143 | 147 | |
144 | 148 | Py_LOCAL_INLINE(double) |