14
14
import os
15
15
import pickle
16
16
import select
17
+ import selectors
17
18
import shutil
18
19
import signal
19
20
import socket
@@ -3940,6 +3941,11 @@ def timerfd_create(self, *args, **kwargs):
3940
3941
self .addCleanup (os .close , fd )
3941
3942
return fd
3942
3943
3944
+ def read_count_signaled (self , fd ):
3945
+ # read 8 bytes
3946
+ data = os .read (fd , 8 )
3947
+ return int .from_bytes (data , byteorder = sys .byteorder )
3948
+
3943
3949
def test_timerfd_initval (self ):
3944
3950
fd = self .timerfd_create (time .CLOCK_REALTIME )
3945
3951
@@ -3962,25 +3968,22 @@ def test_timerfd_initval(self):
3962
3968
self .assertAlmostEqual (next_expiration , initial_expiration , places = 3 )
3963
3969
3964
3970
def test_timerfd_non_blocking (self ):
3965
- size = 8 # read 8 bytes
3966
3971
fd = self .timerfd_create (time .CLOCK_REALTIME , flags = os .TFD_NONBLOCK )
3967
3972
3968
3973
# 0.1 second later
3969
3974
initial_expiration = 0.1
3970
- _ , _ = os .timerfd_settime (fd , initial = initial_expiration , interval = 0 )
3975
+ os .timerfd_settime (fd , initial = initial_expiration , interval = 0 )
3971
3976
3972
3977
# read() raises OSError with errno is EAGAIN for non-blocking timer.
3973
3978
with self .assertRaises (OSError ) as ctx :
3974
- _ = os . read (fd , size )
3979
+ self . read_count_signaled (fd )
3975
3980
self .assertEqual (ctx .exception .errno , errno .EAGAIN )
3976
3981
3977
3982
# Wait more than 0.1 seconds
3978
3983
time .sleep (initial_expiration + 0.1 )
3979
3984
3980
3985
# confirm if timerfd is readable and read() returns 1 as bytes.
3981
- n = os .read (fd , size )
3982
- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
3983
- self .assertEqual (count_signaled , 1 )
3986
+ self .assertEqual (self .read_count_signaled (fd ), 1 )
3984
3987
3985
3988
def test_timerfd_negative (self ):
3986
3989
one_sec_in_nsec = 10 ** 9
@@ -3995,25 +3998,24 @@ def test_timerfd_negative(self):
3995
3998
for flags in test_flags :
3996
3999
with self .subTest (flags = flags , initial = initial , interval = interval ):
3997
4000
with self .assertRaises (OSError ) as context :
3998
- _ , _ = os .timerfd_settime (fd , flags = flags , initial = initial , interval = interval )
4001
+ os .timerfd_settime (fd , flags = flags , initial = initial , interval = interval )
3999
4002
self .assertEqual (context .exception .errno , errno .EINVAL )
4000
4003
4001
4004
with self .assertRaises (OSError ) as context :
4002
4005
initial_ns = int ( one_sec_in_nsec * initial )
4003
4006
interval_ns = int ( one_sec_in_nsec * interval )
4004
- _ , _ = os .timerfd_settime_ns (fd , flags = flags , initial = initial_ns , interval = interval_ns )
4007
+ os .timerfd_settime_ns (fd , flags = flags , initial = initial_ns , interval = interval_ns )
4005
4008
self .assertEqual (context .exception .errno , errno .EINVAL )
4006
4009
4007
4010
def test_timerfd_interval (self ):
4008
- size = 8 # read 8 bytes
4009
4011
fd = self .timerfd_create (time .CLOCK_REALTIME )
4010
4012
4011
4013
# 1 second
4012
4014
initial_expiration = 1
4013
4015
# 0.5 second
4014
4016
interval = 0.5
4015
4017
4016
- _ , _ = os .timerfd_settime (fd , initial = initial_expiration , interval = interval )
4018
+ os .timerfd_settime (fd , initial = initial_expiration , interval = interval )
4017
4019
4018
4020
# timerfd_gettime
4019
4021
next_expiration , interval2 = os .timerfd_gettime (fd )
@@ -4023,22 +4025,17 @@ def test_timerfd_interval(self):
4023
4025
count = 3
4024
4026
t = time .perf_counter ()
4025
4027
for _ in range (count ):
4026
- n = os .read (fd , size )
4027
- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4028
- self .assertEqual (count_signaled , 1 )
4028
+ self .assertEqual (self .read_count_signaled (fd ), 1 )
4029
4029
t = time .perf_counter () - t
4030
4030
4031
4031
total_time = initial_expiration + interval * (count - 1 )
4032
4032
self .assertGreater (t , total_time )
4033
4033
4034
4034
# wait 3.5 time of interval
4035
4035
time .sleep ( (count + 0.5 ) * interval )
4036
- n = os .read (fd , size )
4037
- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4038
- self .assertEqual (count_signaled , count )
4036
+ self .assertEqual (self .read_count_signaled (fd ), count )
4039
4037
4040
4038
def test_timerfd_TFD_TIMER_ABSTIME (self ):
4041
- size = 8 # read 8 bytes
4042
4039
fd = self .timerfd_create (time .CLOCK_REALTIME )
4043
4040
4044
4041
now = time .clock_gettime (time .CLOCK_REALTIME )
@@ -4049,7 +4046,7 @@ def test_timerfd_TFD_TIMER_ABSTIME(self):
4049
4046
# not interval timer
4050
4047
interval = 0
4051
4048
4052
- _ , _ = os .timerfd_settime (fd , flags = os .TFD_TIMER_ABSTIME , initial = initial_expiration , interval = interval )
4049
+ os .timerfd_settime (fd , flags = os .TFD_TIMER_ABSTIME , initial = initial_expiration , interval = interval )
4053
4050
4054
4051
# timerfd_gettime
4055
4052
# Note: timerfd_gettime returns relative values even if TFD_TIMER_ABSTIME is specified.
@@ -4058,15 +4055,13 @@ def test_timerfd_TFD_TIMER_ABSTIME(self):
4058
4055
self .assertAlmostEqual (next_expiration , offset , places = 3 )
4059
4056
4060
4057
t = time .perf_counter ()
4061
- n = os .read (fd , size )
4062
- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4058
+ count_signaled = self .read_count_signaled (fd )
4063
4059
t = time .perf_counter () - t
4064
4060
self .assertEqual (count_signaled , 1 )
4065
4061
4066
4062
self .assertGreater (t , offset - self .CLOCK_RES )
4067
4063
4068
4064
def test_timerfd_select (self ):
4069
- size = 8 # read 8 bytes
4070
4065
fd = self .timerfd_create (time .CLOCK_REALTIME , flags = os .TFD_NONBLOCK )
4071
4066
4072
4067
rfd , wfd , xfd = select .select ([fd ], [fd ], [fd ], 0 )
@@ -4077,56 +4072,74 @@ def test_timerfd_select(self):
4077
4072
# every 0.125 second
4078
4073
interval = 0.125
4079
4074
4080
- _ , _ = os .timerfd_settime (fd , initial = initial_expiration , interval = interval )
4075
+ os .timerfd_settime (fd , initial = initial_expiration , interval = interval )
4081
4076
4082
4077
count = 3
4083
4078
t = time .perf_counter ()
4084
4079
for _ in range (count ):
4085
4080
rfd , wfd , xfd = select .select ([fd ], [fd ], [fd ], initial_expiration + interval )
4086
4081
self .assertEqual ((rfd , wfd , xfd ), ([fd ], [], []))
4087
- n = os .read (fd , size )
4088
- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4089
- self .assertEqual (count_signaled , 1 )
4082
+ self .assertEqual (self .read_count_signaled (fd ), 1 )
4090
4083
t = time .perf_counter () - t
4091
4084
4092
4085
total_time = initial_expiration + interval * (count - 1 )
4093
4086
self .assertGreater (t , total_time )
4094
4087
4095
- def test_timerfd_epoll (self ):
4096
- size = 8 # read 8 bytes
4088
+ def check_timerfd_poll (self , nanoseconds ):
4097
4089
fd = self .timerfd_create (time .CLOCK_REALTIME , flags = os .TFD_NONBLOCK )
4098
4090
4099
- ep = select . epoll ()
4100
- ep .register (fd , select . EPOLLIN )
4101
- self .addCleanup (ep .close )
4091
+ selector = selectors . DefaultSelector ()
4092
+ selector .register (fd , selectors . EVENT_READ )
4093
+ self .addCleanup (selector .close )
4102
4094
4095
+ sec_to_nsec = 10 ** 9
4103
4096
# 0.25 second
4104
- initial_expiration = 0.25
4097
+ initial_expiration_ns = sec_to_nsec // 4
4105
4098
# every 0.125 second
4106
- interval = 0.125
4099
+ interval_ns = sec_to_nsec // 8
4107
4100
4108
- _ , _ = os .timerfd_settime (fd , initial = initial_expiration , interval = interval )
4101
+ if nanoseconds :
4102
+ os .timerfd_settime_ns (fd ,
4103
+ initial = initial_expiration_ns ,
4104
+ interval = interval_ns )
4105
+ else :
4106
+ os .timerfd_settime (fd ,
4107
+ initial = initial_expiration_ns / sec_to_nsec ,
4108
+ interval = interval_ns / sec_to_nsec )
4109
4109
4110
4110
count = 3
4111
- t = time .perf_counter ()
4111
+ if nanoseconds :
4112
+ t = time .perf_counter_ns ()
4113
+ else :
4114
+ t = time .perf_counter ()
4112
4115
for i in range (count ):
4113
- timeout_margin = interval
4116
+ timeout_margin_ns = interval_ns
4114
4117
if i == 0 :
4115
- timeout = initial_expiration + interval + timeout_margin
4118
+ timeout_ns = initial_expiration_ns + interval_ns + timeout_margin_ns
4116
4119
else :
4117
- timeout = interval + timeout_margin
4118
- # epoll timeout is in seconds.
4119
- events = ep .poll (timeout )
4120
- self .assertEqual (events , [(fd , select .EPOLLIN )])
4121
- n = os .read (fd , size )
4122
- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4123
- self .assertEqual (count_signaled , 1 )
4120
+ timeout_ns = interval_ns + timeout_margin_ns
4124
4121
4125
- t = time .perf_counter () - t
4122
+ ready = selector .select (timeout_ns / sec_to_nsec )
4123
+ self .assertEqual (len (ready ), 1 , ready )
4124
+ event = ready [0 ][1 ]
4125
+ self .assertEqual (event , selectors .EVENT_READ )
4126
4126
4127
- total_time = initial_expiration + interval * (count - 1 )
4128
- self .assertGreater (t , total_time )
4129
- ep .unregister (fd )
4127
+ self .assertEqual (self .read_count_signaled (fd ), 1 )
4128
+
4129
+ total_time = initial_expiration_ns + interval_ns * (count - 1 )
4130
+ if nanoseconds :
4131
+ dt = time .perf_counter_ns () - t
4132
+ self .assertGreater (dt , total_time )
4133
+ else :
4134
+ dt = time .perf_counter () - t
4135
+ self .assertGreater (dt , total_time / sec_to_nsec )
4136
+ selector .unregister (fd )
4137
+
4138
+ def test_timerfd_poll (self ):
4139
+ self .check_timerfd_poll (False )
4140
+
4141
+ def test_timerfd_ns_poll (self ):
4142
+ self .check_timerfd_poll (True )
4130
4143
4131
4144
def test_timerfd_ns_initval (self ):
4132
4145
one_sec_in_nsec = 10 ** 9
@@ -4153,7 +4166,6 @@ def test_timerfd_ns_initval(self):
4153
4166
self .assertAlmostEqual (next_expiration_ns , initial_expiration_ns , delta = limit_error )
4154
4167
4155
4168
def test_timerfd_ns_interval (self ):
4156
- size = 8 # read 8 bytes
4157
4169
one_sec_in_nsec = 10 ** 9
4158
4170
limit_error = one_sec_in_nsec // 10 ** 3
4159
4171
fd = self .timerfd_create (time .CLOCK_REALTIME )
@@ -4163,7 +4175,7 @@ def test_timerfd_ns_interval(self):
4163
4175
# every 0.5 second
4164
4176
interval_ns = one_sec_in_nsec // 2
4165
4177
4166
- _ , _ = os .timerfd_settime_ns (fd , initial = initial_expiration_ns , interval = interval_ns )
4178
+ os .timerfd_settime_ns (fd , initial = initial_expiration_ns , interval = interval_ns )
4167
4179
4168
4180
# timerfd_gettime
4169
4181
next_expiration_ns , interval_ns2 = os .timerfd_gettime_ns (fd )
@@ -4173,23 +4185,18 @@ def test_timerfd_ns_interval(self):
4173
4185
count = 3
4174
4186
t = time .perf_counter_ns ()
4175
4187
for _ in range (count ):
4176
- n = os .read (fd , size )
4177
- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4178
- self .assertEqual (count_signaled , 1 )
4188
+ self .assertEqual (self .read_count_signaled (fd ), 1 )
4179
4189
t = time .perf_counter_ns () - t
4180
4190
4181
4191
total_time_ns = initial_expiration_ns + interval_ns * (count - 1 )
4182
4192
self .assertGreater (t , total_time_ns )
4183
4193
4184
4194
# wait 3.5 time of interval
4185
4195
time .sleep ( (count + 0.5 ) * interval_ns / one_sec_in_nsec )
4186
- n = os .read (fd , size )
4187
- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4188
- self .assertEqual (count_signaled , count )
4196
+ self .assertEqual (self .read_count_signaled (fd ), count )
4189
4197
4190
4198
4191
4199
def test_timerfd_ns_TFD_TIMER_ABSTIME (self ):
4192
- size = 8 # read 8 bytes
4193
4200
one_sec_in_nsec = 10 ** 9
4194
4201
limit_error = one_sec_in_nsec // 10 ** 3
4195
4202
fd = self .timerfd_create (time .CLOCK_REALTIME )
@@ -4202,7 +4209,7 @@ def test_timerfd_ns_TFD_TIMER_ABSTIME(self):
4202
4209
# not interval timer
4203
4210
interval_ns = 0
4204
4211
4205
- _ , _ = os .timerfd_settime_ns (fd , flags = os .TFD_TIMER_ABSTIME , initial = initial_expiration_ns , interval = interval_ns )
4212
+ os .timerfd_settime_ns (fd , flags = os .TFD_TIMER_ABSTIME , initial = initial_expiration_ns , interval = interval_ns )
4206
4213
4207
4214
# timerfd_gettime
4208
4215
# Note: timerfd_gettime returns relative values even if TFD_TIMER_ABSTIME is specified.
@@ -4211,15 +4218,13 @@ def test_timerfd_ns_TFD_TIMER_ABSTIME(self):
4211
4218
self .assertLess (abs (next_expiration_ns - offset_ns ), limit_error )
4212
4219
4213
4220
t = time .perf_counter_ns ()
4214
- n = os .read (fd , size )
4215
- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4221
+ count_signaled = self .read_count_signaled (fd )
4216
4222
t = time .perf_counter_ns () - t
4217
4223
self .assertEqual (count_signaled , 1 )
4218
4224
4219
4225
self .assertGreater (t , offset_ns - self .CLOCK_RES_NS )
4220
4226
4221
4227
def test_timerfd_ns_select (self ):
4222
- size = 8 # read 8 bytes
4223
4228
one_sec_in_nsec = 10 ** 9
4224
4229
4225
4230
fd = self .timerfd_create (time .CLOCK_REALTIME , flags = os .TFD_NONBLOCK )
@@ -4232,59 +4237,19 @@ def test_timerfd_ns_select(self):
4232
4237
# every 0.125 second
4233
4238
interval_ns = one_sec_in_nsec // 8
4234
4239
4235
- _ , _ = os .timerfd_settime_ns (fd , initial = initial_expiration_ns , interval = interval_ns )
4240
+ os .timerfd_settime_ns (fd , initial = initial_expiration_ns , interval = interval_ns )
4236
4241
4237
4242
count = 3
4238
4243
t = time .perf_counter_ns ()
4239
4244
for _ in range (count ):
4240
4245
rfd , wfd , xfd = select .select ([fd ], [fd ], [fd ], (initial_expiration_ns + interval_ns ) / 1e9 )
4241
4246
self .assertEqual ((rfd , wfd , xfd ), ([fd ], [], []))
4242
- n = os .read (fd , size )
4243
- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4244
- self .assertEqual (count_signaled , 1 )
4247
+ self .assertEqual (self .read_count_signaled (fd ), 1 )
4245
4248
t = time .perf_counter_ns () - t
4246
4249
4247
4250
total_time_ns = initial_expiration_ns + interval_ns * (count - 1 )
4248
4251
self .assertGreater (t , total_time_ns )
4249
4252
4250
- def test_timerfd_ns_epoll (self ):
4251
- size = 8 # read 8 bytes
4252
- one_sec_in_nsec = 10 ** 9
4253
- fd = self .timerfd_create (time .CLOCK_REALTIME , flags = os .TFD_NONBLOCK )
4254
-
4255
- ep = select .epoll ()
4256
- ep .register (fd , select .EPOLLIN )
4257
- self .addCleanup (ep .close )
4258
-
4259
- # 0.25 second
4260
- initial_expiration_ns = one_sec_in_nsec // 4
4261
- # every 0.125 second
4262
- interval_ns = one_sec_in_nsec // 8
4263
-
4264
- _ , _ = os .timerfd_settime_ns (fd , initial = initial_expiration_ns , interval = interval_ns )
4265
-
4266
- count = 3
4267
- t = time .perf_counter_ns ()
4268
- for i in range (count ):
4269
- timeout_margin_ns = interval_ns
4270
- if i == 0 :
4271
- timeout_ns = initial_expiration_ns + interval_ns + timeout_margin_ns
4272
- else :
4273
- timeout_ns = interval_ns + timeout_margin_ns
4274
-
4275
- # epoll timeout is in seconds.
4276
- events = ep .poll (timeout_ns / one_sec_in_nsec )
4277
- self .assertEqual (events , [(fd , select .EPOLLIN )])
4278
- n = os .read (fd , size )
4279
- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4280
- self .assertEqual (count_signaled , 1 )
4281
-
4282
- t = time .perf_counter_ns () - t
4283
-
4284
- total_time = initial_expiration_ns + interval_ns * (count - 1 )
4285
- self .assertGreater (t , total_time )
4286
- ep .unregister (fd )
4287
-
4288
4253
class OSErrorTests (unittest .TestCase ):
4289
4254
def setUp (self ):
4290
4255
class Str (str ):
0 commit comments