22import random
33import signal
44import socket
5+ import statistics
56import subprocess
67import sys
78import time
@@ -949,13 +950,55 @@ class StressTest(unittest.TestCase):
949950 previously tripped signal handlers.
950951 """
951952
953+ def setsig (self , signum , handler ):
954+ old_handler = signal .signal (signum , handler )
955+ self .addCleanup (signal .signal , signum , old_handler )
956+
957+ def measure_itimer_resolution (self ):
958+ N = 20
959+ times = []
960+
961+ def handler (signum = None , frame = None ):
962+ if len (times ) < N :
963+ times .append (time .perf_counter ())
964+ # 1 µs is the smallest possible timer interval,
965+ # we want to measure what the concrete duration
966+ # will be on this platform
967+ signal .setitimer (signal .ITIMER_REAL , 1e-6 )
968+
969+ self .addCleanup (signal .setitimer , signal .ITIMER_REAL , 0 )
970+ self .setsig (signal .SIGALRM , handler )
971+ handler ()
972+ while len (times ) < N :
973+ time .sleep (1e-3 )
974+
975+ durations = [times [i + 1 ] - times [i ] for i in range (len (times ) - 1 )]
976+ med = statistics .median (durations )
977+ if support .verbose :
978+ print ("detected median itimer() resolution: %.6f s." % (med ,))
979+ return med
980+
981+ def decide_itimer_count (self ):
982+ # Some systems have poor setitimer() resolution (for example
983+ # measured around 20 ms. on FreeBSD 9), so decide on a reasonable
984+ # number of sequential timers based on that.
985+ reso = self .measure_itimer_resolution ()
986+ if reso <= 1e-4 :
987+ return 10000
988+ elif reso <= 1e-2 :
989+ return 100
990+ else :
991+ self .skipTest ("detected itimer resolution (%.3f s.) too high "
992+ "(> 10 ms.) on this platform (or system too busy)"
993+ % (reso ,))
994+
952995 @unittest .skipUnless (hasattr (signal , "setitimer" ),
953996 "test needs setitimer()" )
954997 def test_stress_delivery_dependent (self ):
955998 """
956999 This test uses dependent signal handlers.
9571000 """
958- N = 10000
1001+ N = self . decide_itimer_count ()
9591002 sigs = []
9601003
9611004 def first_handler (signum , frame ):
@@ -969,16 +1012,12 @@ def first_handler(signum, frame):
9691012 def second_handler (signum = None , frame = None ):
9701013 sigs .append (signum )
9711014
972- def setsig (signum , handler ):
973- old_handler = signal .signal (signum , handler )
974- self .addCleanup (signal .signal , signum , old_handler )
975-
9761015 # Here on Linux, SIGPROF > SIGALRM > SIGUSR1. By using both
9771016 # ascending and descending sequences (SIGUSR1 then SIGALRM,
9781017 # SIGPROF then SIGALRM), we maximize chances of hitting a bug.
979- setsig (signal .SIGPROF , first_handler )
980- setsig (signal .SIGUSR1 , first_handler )
981- setsig (signal .SIGALRM , second_handler ) # for ITIMER_REAL
1018+ self . setsig (signal .SIGPROF , first_handler )
1019+ self . setsig (signal .SIGUSR1 , first_handler )
1020+ self . setsig (signal .SIGALRM , second_handler ) # for ITIMER_REAL
9821021
9831022 expected_sigs = 0
9841023 deadline = time .time () + 15.0
@@ -1005,18 +1044,14 @@ def test_stress_delivery_simultaneous(self):
10051044 """
10061045 This test uses simultaneous signal handlers.
10071046 """
1008- N = 10000
1047+ N = self . decide_itimer_count ()
10091048 sigs = []
10101049
10111050 def handler (signum , frame ):
10121051 sigs .append (signum )
10131052
1014- def setsig (signum , handler ):
1015- old_handler = signal .signal (signum , handler )
1016- self .addCleanup (signal .signal , signum , old_handler )
1017-
1018- setsig (signal .SIGUSR1 , handler )
1019- setsig (signal .SIGALRM , handler ) # for ITIMER_REAL
1053+ self .setsig (signal .SIGUSR1 , handler )
1054+ self .setsig (signal .SIGALRM , handler ) # for ITIMER_REAL
10201055
10211056 expected_sigs = 0
10221057 deadline = time .time () + 15.0
0 commit comments