99import select
1010import signal
1111import socket
12- import struct
12+ import statistics
1313import subprocess
1414import traceback
1515import sys , os , time , errno
@@ -964,13 +964,55 @@ class StressTest(unittest.TestCase):
964964 previously tripped signal handlers.
965965 """
966966
967+ def setsig (self , signum , handler ):
968+ old_handler = signal .signal (signum , handler )
969+ self .addCleanup (signal .signal , signum , old_handler )
970+
971+ def measure_itimer_resolution (self ):
972+ N = 20
973+ times = []
974+
975+ def handler (signum = None , frame = None ):
976+ if len (times ) < N :
977+ times .append (time .perf_counter ())
978+ # 1 µs is the smallest possible timer interval,
979+ # we want to measure what the concrete duration
980+ # will be on this platform
981+ signal .setitimer (signal .ITIMER_REAL , 1e-6 )
982+
983+ self .addCleanup (signal .setitimer , signal .ITIMER_REAL , 0 )
984+ self .setsig (signal .SIGALRM , handler )
985+ handler ()
986+ while len (times ) < N :
987+ time .sleep (1e-3 )
988+
989+ durations = [times [i + 1 ] - times [i ] for i in range (len (times ) - 1 )]
990+ med = statistics .median (durations )
991+ if support .verbose :
992+ print ("detected median itimer() resolution: %.6f s." % (med ,))
993+ return med
994+
995+ def decide_itimer_count (self ):
996+ # Some systems have poor setitimer() resolution (for example
997+ # measured around 20 ms. on FreeBSD 9), so decide on a reasonable
998+ # number of sequential timers based on that.
999+ reso = self .measure_itimer_resolution ()
1000+ if reso <= 1e-4 :
1001+ return 10000
1002+ elif reso <= 1e-2 :
1003+ return 100
1004+ else :
1005+ self .skipTest ("detected itimer resolution (%.3f s.) too high "
1006+ "(> 10 ms.) on this platform (or system too busy)"
1007+ % (reso ,))
1008+
9671009 @unittest .skipUnless (hasattr (signal , "setitimer" ),
9681010 "test needs setitimer()" )
9691011 def test_stress_delivery_dependent (self ):
9701012 """
9711013 This test uses dependent signal handlers.
9721014 """
973- N = 10000
1015+ N = self . decide_itimer_count ()
9741016 sigs = []
9751017
9761018 def first_handler (signum , frame ):
@@ -984,16 +1026,12 @@ def first_handler(signum, frame):
9841026 def second_handler (signum = None , frame = None ):
9851027 sigs .append (signum )
9861028
987- def setsig (signum , handler ):
988- old_handler = signal .signal (signum , handler )
989- self .addCleanup (signal .signal , signum , old_handler )
990-
9911029 # Here on Linux, SIGPROF > SIGALRM > SIGUSR1. By using both
9921030 # ascending and descending sequences (SIGUSR1 then SIGALRM,
9931031 # SIGPROF then SIGALRM), we maximize chances of hitting a bug.
994- setsig (signal .SIGPROF , first_handler )
995- setsig (signal .SIGUSR1 , first_handler )
996- setsig (signal .SIGALRM , second_handler ) # for ITIMER_REAL
1032+ self . setsig (signal .SIGPROF , first_handler )
1033+ self . setsig (signal .SIGUSR1 , first_handler )
1034+ self . setsig (signal .SIGALRM , second_handler ) # for ITIMER_REAL
9971035
9981036 expected_sigs = 0
9991037 deadline = time .time () + 15.0
@@ -1020,18 +1058,14 @@ def test_stress_delivery_simultaneous(self):
10201058 """
10211059 This test uses simultaneous signal handlers.
10221060 """
1023- N = 10000
1061+ N = self . decide_itimer_count ()
10241062 sigs = []
10251063
10261064 def handler (signum , frame ):
10271065 sigs .append (signum )
10281066
1029- def setsig (signum , handler ):
1030- old_handler = signal .signal (signum , handler )
1031- self .addCleanup (signal .signal , signum , old_handler )
1032-
1033- setsig (signal .SIGUSR1 , handler )
1034- setsig (signal .SIGALRM , handler ) # for ITIMER_REAL
1067+ self .setsig (signal .SIGUSR1 , handler )
1068+ self .setsig (signal .SIGALRM , handler ) # for ITIMER_REAL
10351069
10361070 expected_sigs = 0
10371071 deadline = time .time () + 15.0
0 commit comments