diff --git a/Lib/socket.py b/Lib/socket.py index d0da7409bb0..95901aeca1c 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -130,7 +130,13 @@ class socket(_socket.socket): For IP sockets, the address info is a pair (hostaddr, port). """ fd, addr = self._accept() - return socket(self.family, self.type, self.proto, fileno=fd), addr + sock = socket(self.family, self.type, self.proto, fileno=fd) + # Issue #7995: if no default timeout is set and the listening + # socket had a (non-zero) timeout, force the new socket in blocking + # mode to override platform-specific socket flags inheritance. + if getdefaulttimeout() is None and self.gettimeout(): + sock.setblocking(True) + return sock, addr def makefile(self, mode="r", buffering=None, *, encoding=None, errors=None, newline=None): diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 8f96fe48a31..23d22a8695f 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -982,6 +982,23 @@ class NonBlockingTCPTests(ThreadedTCPSocketTest): def _testInitNonBlocking(self): pass + def testInheritFlags(self): + # Issue #7995: when calling accept() on a listening socket with a + # timeout, the resulting socket should not be non-blocking. + self.serv.settimeout(10) + try: + conn, addr = self.serv.accept() + message = conn.recv(len(MSG)) + finally: + conn.close() + self.serv.settimeout(None) + + def _testInheritFlags(self): + time.sleep(0.1) + self.cli.connect((HOST, self.port)) + time.sleep(0.5) + self.cli.send(MSG) + def testAccept(self): # Testing non-blocking accept self.serv.setblocking(0) diff --git a/Misc/NEWS b/Misc/NEWS index 1081fc4d0e6..5050ae82759 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -30,6 +30,9 @@ Core and Builtins Library ------- +- Issue #7995: When calling accept() on a socket with a timeout, the returned + socket is now always non-blocking, regardless of the operating system. + - Issue #10756: atexit normalizes the exception before displaying it. Patch by Andreas Stührk.