3434 fcntl = None
3535
3636HOST = support .HOST
37- MSG = 'Michael Gilfix was here\u1234 \r \n ' .encode ('utf-8' ) ## test unicode string and carriage return
37+ # test unicode string and carriage return
38+ MSG = 'Michael Gilfix was here\u1234 \r \n ' .encode ('utf-8' )
3839MAIN_TIMEOUT = 60.0
3940
4041VSOCKPORT = 1234
@@ -111,9 +112,14 @@ def _have_socket_vsock():
111112 return ret
112113
113114
114- def _is_fd_in_blocking_mode (sock ):
115- return not bool (
116- fcntl .fcntl (sock , fcntl .F_GETFL , os .O_NONBLOCK ) & os .O_NONBLOCK )
115+ @contextlib .contextmanager
116+ def socket_setdefaulttimeout (timeout ):
117+ old_timeout = socket .getdefaulttimeout ()
118+ try :
119+ socket .setdefaulttimeout (timeout )
120+ yield
121+ finally :
122+ socket .setdefaulttimeout (old_timeout )
117123
118124
119125HAVE_SOCKET_CAN = _have_socket_can ()
@@ -1069,18 +1075,16 @@ def testDefaultTimeout(self):
10691075 s .close ()
10701076
10711077 # Set the default timeout to 10, and see if it propagates
1072- socket .setdefaulttimeout (10 )
1073- self .assertEqual (socket .getdefaulttimeout (), 10 )
1074- s = socket .socket ()
1075- self .assertEqual (s .gettimeout (), 10 )
1076- s .close ()
1078+ with socket_setdefaulttimeout (10 ):
1079+ self .assertEqual (socket .getdefaulttimeout (), 10 )
1080+ with socket .socket () as sock :
1081+ self .assertEqual (sock .gettimeout (), 10 )
10771082
1078- # Reset the default timeout to None, and see if it propagates
1079- socket .setdefaulttimeout (None )
1080- self .assertEqual (socket .getdefaulttimeout (), None )
1081- s = socket .socket ()
1082- self .assertEqual (s .gettimeout (), None )
1083- s .close ()
1083+ # Reset the default timeout to None, and see if it propagates
1084+ socket .setdefaulttimeout (None )
1085+ self .assertEqual (socket .getdefaulttimeout (), None )
1086+ with socket .socket () as sock :
1087+ self .assertEqual (sock .gettimeout (), None )
10841088
10851089 # Check that setting it to an invalid value raises ValueError
10861090 self .assertRaises (ValueError , socket .setdefaulttimeout , - 1 )
@@ -4218,55 +4222,42 @@ def __init__(self, methodName='runTest'):
42184222 self .event = threading .Event ()
42194223 ThreadedTCPSocketTest .__init__ (self , methodName = methodName )
42204224
4225+ def assert_sock_timeout (self , sock , timeout ):
4226+ self .assertEqual (self .serv .gettimeout (), timeout )
4227+
4228+ blocking = (timeout != 0.0 )
4229+ self .assertEqual (sock .getblocking (), blocking )
4230+
4231+ if fcntl is not None :
4232+ # When a Python socket has a non-zero timeout, it's switched
4233+ # internally to a non-blocking mode. Later, sock.sendall(),
4234+ # sock.recv(), and other socket operations use a select() call and
4235+ # handle EWOULDBLOCK/EGAIN on all socket operations. That's how
4236+ # timeouts are enforced.
4237+ fd_blocking = (timeout is None )
4238+
4239+ flag = fcntl .fcntl (sock , fcntl .F_GETFL , os .O_NONBLOCK )
4240+ self .assertEqual (not bool (flag & os .O_NONBLOCK ), fd_blocking )
4241+
42214242 def testSetBlocking (self ):
4222- # Testing whether set blocking works
4243+ # Test setblocking() and settimeout() methods
42234244 self .serv .setblocking (True )
4224- self .assertIsNone (self .serv .gettimeout ())
4225- self .assertTrue (self .serv .getblocking ())
4226- if fcntl :
4227- self .assertTrue (_is_fd_in_blocking_mode (self .serv ))
4245+ self .assert_sock_timeout (self .serv , None )
42284246
42294247 self .serv .setblocking (False )
4230- self .assertEqual (self .serv .gettimeout (), 0.0 )
4231- self .assertFalse (self .serv .getblocking ())
4232- if fcntl :
4233- self .assertFalse (_is_fd_in_blocking_mode (self .serv ))
4248+ self .assert_sock_timeout (self .serv , 0.0 )
42344249
42354250 self .serv .settimeout (None )
4236- self .assertTrue (self .serv .getblocking ())
4237- if fcntl :
4238- self .assertTrue (_is_fd_in_blocking_mode (self .serv ))
4251+ self .assert_sock_timeout (self .serv , None )
42394252
42404253 self .serv .settimeout (0 )
4241- self .assertFalse (self .serv .getblocking ())
4242- self .assertEqual (self .serv .gettimeout (), 0 )
4243- if fcntl :
4244- self .assertFalse (_is_fd_in_blocking_mode (self .serv ))
4254+ self .assert_sock_timeout (self .serv , 0 )
42454255
42464256 self .serv .settimeout (10 )
4247- self .assertTrue (self .serv .getblocking ())
4248- self .assertEqual (self .serv .gettimeout (), 10 )
4249- if fcntl :
4250- # When a Python socket has a non-zero timeout, it's
4251- # switched internally to a non-blocking mode.
4252- # Later, sock.sendall(), sock.recv(), and other socket
4253- # operations use a `select()` call and handle EWOULDBLOCK/EGAIN
4254- # on all socket operations. That's how timeouts are
4255- # enforced.
4256- self .assertFalse (_is_fd_in_blocking_mode (self .serv ))
4257+ self .assert_sock_timeout (self .serv , 10 )
42574258
42584259 self .serv .settimeout (0 )
4259- self .assertFalse (self .serv .getblocking ())
4260- if fcntl :
4261- self .assertFalse (_is_fd_in_blocking_mode (self .serv ))
4262-
4263- start = time .time ()
4264- try :
4265- self .serv .accept ()
4266- except OSError :
4267- pass
4268- end = time .time ()
4269- self .assertTrue ((end - start ) < 1.0 , "Error setting non-blocking mode." )
4260+ self .assert_sock_timeout (self .serv , 0 )
42704261
42714262 def _testSetBlocking (self ):
42724263 pass
@@ -4277,8 +4268,10 @@ def testSetBlocking_overflow(self):
42774268 import _testcapi
42784269 if _testcapi .UINT_MAX >= _testcapi .ULONG_MAX :
42794270 self .skipTest ('needs UINT_MAX < ULONG_MAX' )
4271+
42804272 self .serv .setblocking (False )
42814273 self .assertEqual (self .serv .gettimeout (), 0.0 )
4274+
42824275 self .serv .setblocking (_testcapi .UINT_MAX + 1 )
42834276 self .assertIsNone (self .serv .gettimeout ())
42844277
@@ -4288,50 +4281,51 @@ def testSetBlocking_overflow(self):
42884281 'test needs socket.SOCK_NONBLOCK' )
42894282 @support .requires_linux_version (2 , 6 , 28 )
42904283 def testInitNonBlocking (self ):
4291- # reinit server socket
4284+ # create a socket with SOCK_NONBLOCK
42924285 self .serv .close ()
4293- self .serv = socket .socket (socket .AF_INET , socket .SOCK_STREAM |
4294- socket .SOCK_NONBLOCK )
4295- self .assertFalse (self .serv .getblocking ())
4296- self .assertEqual (self .serv .gettimeout (), 0 )
4297- self .port = support .bind_port (self .serv )
4298- self .serv .listen ()
4299- # actual testing
4300- start = time .time ()
4301- try :
4302- self .serv .accept ()
4303- except OSError :
4304- pass
4305- end = time .time ()
4306- self .assertTrue ((end - start ) < 1.0 , "Error creating with non-blocking mode." )
4286+ self .serv = socket .socket (socket .AF_INET ,
4287+ socket .SOCK_STREAM | socket .SOCK_NONBLOCK )
4288+ self .assert_sock_timeout (self .serv , 0 )
43074289
43084290 def _testInitNonBlocking (self ):
43094291 pass
43104292
4311- def testInheritFlags (self ):
4312- # Issue # 7995: when calling accept() on a listening socket with a
4313- # timeout, the resulting socket should not be non- blocking.
4314- self . serv . settimeout ( 10 )
4315- try :
4293+ def testInheritFlagsBlocking (self ):
4294+ # bpo- 7995: accept() on a listening socket with a timeout and the
4295+ # default timeout is None , the resulting socket must be blocking.
4296+ with socket_setdefaulttimeout ( None ):
4297+ self . serv . settimeout ( 10 )
43164298 conn , addr = self .serv .accept ()
4317- message = conn .recv (len (MSG ))
4318- finally :
4319- conn .close ()
4320- self .serv .settimeout (None )
4299+ self .addCleanup (conn .close )
4300+ self .assertIsNone (conn .gettimeout ())
43214301
4322- def _testInheritFlags (self ):
4323- time .sleep (0.1 )
4302+ def _testInheritFlagsBlocking (self ):
4303+ self .cli .connect ((HOST , self .port ))
4304+
4305+ def testInheritFlagsTimeout (self ):
4306+ # bpo-7995: accept() on a listening socket with a timeout and the
4307+ # default timeout is None, the resulting socket must inherit
4308+ # the default timeout.
4309+ default_timeout = 20.0
4310+ with socket_setdefaulttimeout (default_timeout ):
4311+ self .serv .settimeout (10 )
4312+ conn , addr = self .serv .accept ()
4313+ self .addCleanup (conn .close )
4314+ self .assertEqual (conn .gettimeout (), default_timeout )
4315+
4316+ def _testInheritFlagsTimeout (self ):
43244317 self .cli .connect ((HOST , self .port ))
4325- time .sleep (0.5 )
4326- self .cli .send (MSG )
43274318
43284319 def testAccept (self ):
43294320 # Testing non-blocking accept
43304321 self .serv .setblocking (0 )
43314322
43324323 # connect() didn't start: non-blocking accept() fails
4324+ start_time = time .monotonic ()
43334325 with self .assertRaises (BlockingIOError ):
43344326 conn , addr = self .serv .accept ()
4327+ dt = time .monotonic () - start_time
4328+ self .assertLess (dt , 1.0 )
43354329
43364330 self .event .set ()
43374331
@@ -4351,15 +4345,6 @@ def _testAccept(self):
43514345
43524346 self .cli .connect ((HOST , self .port ))
43534347
4354- def testConnect (self ):
4355- # Testing non-blocking connect
4356- conn , addr = self .serv .accept ()
4357- conn .close ()
4358-
4359- def _testConnect (self ):
4360- self .cli .settimeout (10 )
4361- self .cli .connect ((HOST , self .port ))
4362-
43634348 def testRecv (self ):
43644349 # Testing non-blocking recv
43654350 conn , addr = self .serv .accept ()
0 commit comments