mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-31620: have asyncio/queues not leak memory when you've exceptions during waiting (#3813)
This commit is contained in:
		
							parent
							
								
									c060c7e3d1
								
							
						
					
					
						commit
						c62f0cb3b1
					
				
					 3 changed files with 25 additions and 0 deletions
				
			
		|  | @ -167,6 +167,12 @@ def get(self): | ||||||
|                 yield from getter |                 yield from getter | ||||||
|             except: |             except: | ||||||
|                 getter.cancel()  # Just in case getter is not done yet. |                 getter.cancel()  # Just in case getter is not done yet. | ||||||
|  | 
 | ||||||
|  |                 try: | ||||||
|  |                     self._getters.remove(getter) | ||||||
|  |                 except ValueError: | ||||||
|  |                     pass | ||||||
|  | 
 | ||||||
|                 if not self.empty() and not getter.cancelled(): |                 if not self.empty() and not getter.cancelled(): | ||||||
|                     # We were woken up by put_nowait(), but can't take |                     # We were woken up by put_nowait(), but can't take | ||||||
|                     # the call.  Wake up the next in line. |                     # the call.  Wake up the next in line. | ||||||
|  |  | ||||||
|  | @ -295,6 +295,23 @@ def producer(queue, num_items): | ||||||
|                            loop=self.loop), |                            loop=self.loop), | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|  |     def test_cancelled_getters_not_being_held_in_self_getters(self): | ||||||
|  |         def a_generator(): | ||||||
|  |             yield 0.1 | ||||||
|  |             yield 0.2 | ||||||
|  | 
 | ||||||
|  |         self.loop = self.new_test_loop(a_generator) | ||||||
|  |         @asyncio.coroutine | ||||||
|  |         def consumer(queue): | ||||||
|  |             try: | ||||||
|  |                 item = yield from asyncio.wait_for(queue.get(), 0.1, loop=self.loop) | ||||||
|  |             except asyncio.TimeoutError: | ||||||
|  |                 pass | ||||||
|  | 
 | ||||||
|  |         queue = asyncio.Queue(loop=self.loop, maxsize=5) | ||||||
|  |         self.loop.run_until_complete(self.loop.create_task(consumer(queue))) | ||||||
|  |         self.assertEqual(len(queue._getters), 0) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class QueuePutTests(_QueueTestBase): | class QueuePutTests(_QueueTestBase): | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | an empty asyncio.Queue now doesn't leak memory when queue.get pollers | ||||||
|  | timeout | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Suren Nihalani
						Suren Nihalani