1616ALARMS = []
1717
1818
19-
2019def handle_alarms (signum , frame ):
2120 global ALARMS
22- new_alarms = [(ctx , max (0 , remaining - 1 ),) for ctx , remaining in ALARMS ]
23- expired = [ctx for ctx , remaining in new_alarms if remaining == 0 ]
24- ALARMS = [(ctx , remaining ,) for ctx , remaining in new_alarms if remaining > 0 ]
21+ new_alarms = [(ctx , max (0 , remaining - 1 ),) for ctx , remaining in ALARMS ]
22+ expired = [ctx for ctx , remaining in new_alarms if remaining == 0 ]
23+ ALARMS = [
24+ (
25+ ctx ,
26+ remaining ,
27+ ) for ctx , remaining in new_alarms
28+ if remaining > 0 ]
2529 if ALARMS :
2630 signal .alarm (1 )
2731 for task in expired :
@@ -37,7 +41,11 @@ class SignalTimeout(BaseTimeout):
3741 """
3842
3943 def __init__ (self , seconds , swallow_exc = True ):
40- seconds = int (seconds ) # alarm delay for signal MUST be int
44+
45+ # The alarm delay for a SIGALARM MUST be an integer
46+ # greater than 1. Round up non-integer values.
47+ seconds = max (1 , int (seconds + 0.99 ))
48+
4149 super (SignalTimeout , self ).__init__ (seconds , swallow_exc )
4250
4351 def stop (self ):
@@ -49,23 +57,31 @@ def stop(self):
4957 # Required overrides
5058 def setup_interrupt (self ):
5159 global ALARMS
52- for ctx , remaining in ALARMS :
53- if ctx is self :
54- return
55- if len (ALARMS )== 0 :
60+
61+ # If we have already registered ourself, do nothing and
62+ # return.
63+ if any (ctx is self for ctx , _ in ALARMS ):
64+ return
65+
66+ # If no ALARMS have been set up before, register
67+ # signal.SIGALRM.
68+ if len (ALARMS ) == 0 :
5669 signal .signal (signal .SIGALRM , handle_alarms )
5770 signal .alarm (1 )
71+
72+ # Register our self.seconds value in the global
73+ # ALARMS registry.
5874 ALARMS .append ((self , int (self .seconds ),))
5975
6076 def suppress_interrupt (self ):
6177 global ALARMS
6278 ALARMS = [(ctx , remaining ) for ctx , remaining in ALARMS if ctx is not self ]
63- if len (ALARMS )== 0 :
79+ if len (ALARMS ) == 0 :
6480 signal .alarm (0 )
6581 signal .signal (signal .SIGALRM , signal .SIG_DFL )
6682
6783
68- class signal_timeoutable (base_timeoutable ): #noqa
84+ class signal_timeoutable (base_timeoutable ): # noqa
6985 """A function or method decorator that raises a ``TimeoutException`` to
7086 decorated functions that should not last a certain amount of time.
7187 this one uses ``SignalTimeout`` context manager.
0 commit comments