mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +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
	
	 Miss Islington (bot)
						Miss Islington (bot)