Skip to content

Commit ac4f6d4

Browse files
miss-islingtonasvetlov
authored andcommitted
bpo-31620: have asyncio/queues not leak memory when you've exceptions during waiting (GH-3813) (#4326)
(cherry picked from commit c62f0cb)
1 parent 64f1049 commit ac4f6d4

File tree

3 files changed

+25
-0
lines changed

3 files changed

+25
-0
lines changed

Lib/asyncio/queues.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ def get(self):
167167
yield from getter
168168
except:
169169
getter.cancel() # Just in case getter is not done yet.
170+
171+
try:
172+
self._getters.remove(getter)
173+
except ValueError:
174+
pass
175+
170176
if not self.empty() and not getter.cancelled():
171177
# We were woken up by put_nowait(), but can't take
172178
# the call. Wake up the next in line.

Lib/test/test_asyncio/test_queues.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,23 @@ def producer(queue, num_items):
295295
loop=self.loop),
296296
)
297297

298+
def test_cancelled_getters_not_being_held_in_self_getters(self):
299+
def a_generator():
300+
yield 0.1
301+
yield 0.2
302+
303+
self.loop = self.new_test_loop(a_generator)
304+
@asyncio.coroutine
305+
def consumer(queue):
306+
try:
307+
item = yield from asyncio.wait_for(queue.get(), 0.1, loop=self.loop)
308+
except asyncio.TimeoutError:
309+
pass
310+
311+
queue = asyncio.Queue(loop=self.loop, maxsize=5)
312+
self.loop.run_until_complete(self.loop.create_task(consumer(queue)))
313+
self.assertEqual(len(queue._getters), 0)
314+
298315

299316
class QueuePutTests(_QueueTestBase):
300317

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
an empty asyncio.Queue now doesn't leak memory when queue.get pollers
2+
timeout

0 commit comments

Comments
 (0)