mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	bpo-41317: Remove reader on cancellation in asyncio.loop.sock_accept() (GH-21595)
(cherry picked from commit 0dd98c2d00)
Co-authored-by: Alex Grönholm <alex.gronholm@nextday.fi>
			
			
This commit is contained in:
		
							parent
							
								
									e8dda907fb
								
							
						
					
					
						commit
						4ff8e5ba4f
					
				
					 3 changed files with 27 additions and 7 deletions
				
			
		| 
						 | 
					@ -555,20 +555,19 @@ async def sock_accept(self, sock):
 | 
				
			||||||
        if self._debug and sock.gettimeout() != 0:
 | 
					        if self._debug and sock.gettimeout() != 0:
 | 
				
			||||||
            raise ValueError("the socket must be non-blocking")
 | 
					            raise ValueError("the socket must be non-blocking")
 | 
				
			||||||
        fut = self.create_future()
 | 
					        fut = self.create_future()
 | 
				
			||||||
        self._sock_accept(fut, False, sock)
 | 
					        self._sock_accept(fut, sock)
 | 
				
			||||||
        return await fut
 | 
					        return await fut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _sock_accept(self, fut, registered, sock):
 | 
					    def _sock_accept(self, fut, sock):
 | 
				
			||||||
        fd = sock.fileno()
 | 
					        fd = sock.fileno()
 | 
				
			||||||
        if registered:
 | 
					 | 
				
			||||||
            self.remove_reader(fd)
 | 
					 | 
				
			||||||
        if fut.done():
 | 
					 | 
				
			||||||
            return
 | 
					 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            conn, address = sock.accept()
 | 
					            conn, address = sock.accept()
 | 
				
			||||||
            conn.setblocking(False)
 | 
					            conn.setblocking(False)
 | 
				
			||||||
        except (BlockingIOError, InterruptedError):
 | 
					        except (BlockingIOError, InterruptedError):
 | 
				
			||||||
            self.add_reader(fd, self._sock_accept, fut, True, sock)
 | 
					            self._ensure_fd_no_transport(fd)
 | 
				
			||||||
 | 
					            handle = self._add_reader(fd, self._sock_accept, fut, sock)
 | 
				
			||||||
 | 
					            fut.add_done_callback(
 | 
				
			||||||
 | 
					                functools.partial(self._sock_read_done, fd, handle=handle))
 | 
				
			||||||
        except (SystemExit, KeyboardInterrupt):
 | 
					        except (SystemExit, KeyboardInterrupt):
 | 
				
			||||||
            raise
 | 
					            raise
 | 
				
			||||||
        except BaseException as exc:
 | 
					        except BaseException as exc:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -415,6 +415,25 @@ def test_sock_accept(self):
 | 
				
			||||||
        conn.close()
 | 
					        conn.close()
 | 
				
			||||||
        listener.close()
 | 
					        listener.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_cancel_sock_accept(self):
 | 
				
			||||||
 | 
					        listener = socket.socket()
 | 
				
			||||||
 | 
					        listener.setblocking(False)
 | 
				
			||||||
 | 
					        listener.bind(('127.0.0.1', 0))
 | 
				
			||||||
 | 
					        listener.listen(1)
 | 
				
			||||||
 | 
					        sockaddr = listener.getsockname()
 | 
				
			||||||
 | 
					        f = asyncio.wait_for(self.loop.sock_accept(listener), 0.1)
 | 
				
			||||||
 | 
					        with self.assertRaises(asyncio.TimeoutError):
 | 
				
			||||||
 | 
					            self.loop.run_until_complete(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        listener.close()
 | 
				
			||||||
 | 
					        client = socket.socket()
 | 
				
			||||||
 | 
					        client.setblocking(False)
 | 
				
			||||||
 | 
					        f = self.loop.sock_connect(client, sockaddr)
 | 
				
			||||||
 | 
					        with self.assertRaises(ConnectionRefusedError):
 | 
				
			||||||
 | 
					            self.loop.run_until_complete(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        client.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_create_connection_sock(self):
 | 
					    def test_create_connection_sock(self):
 | 
				
			||||||
        with test_utils.run_test_server() as httpd:
 | 
					        with test_utils.run_test_server() as httpd:
 | 
				
			||||||
            sock = None
 | 
					            sock = None
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					Use add_done_callback() in asyncio.loop.sock_accept() to unsubscribe reader
 | 
				
			||||||
 | 
					early on cancellation.
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue