diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index ce657fc1b6a058..ebedfec7fa3f5f 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -1,6 +1,7 @@ """Tests for futures.py.""" import concurrent.futures +import gc import re import sys import threading @@ -19,9 +20,11 @@ def _fakefunc(f): return f + def first_cb(): pass + def last_cb(): pass @@ -483,6 +486,15 @@ def test_future_iter_throw(self): Exception("elephant"), Exception("elephant")) self.assertRaises(TypeError, fi.throw, list) + def test_future_del_collect(self): + class Evil: + def __del__(self): + gc.collect() + + for i in range(100): + fut = self._new_future(loop=self.loop) + fut.set_result(Evil()) + @unittest.skipUnless(hasattr(futures, '_CFuture'), 'requires the C _asyncio module') diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 686387f4f21d85..36082ec7c6a79a 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -3,6 +3,7 @@ import collections import contextlib import functools +import gc import io import os import re @@ -91,6 +92,20 @@ def setUp(self): self.loop.set_task_factory(self.new_task) self.loop.create_future = lambda: self.new_future(self.loop) + def test_task_del_collect(self): + class Evil: + def __del__(self): + gc.collect() + + @asyncio.coroutine + def run(): + return Evil() + + self.loop.run_until_complete( + asyncio.gather(*[ + self.new_task(self.loop, run()) for _ in range(100) + ], loop=self.loop)) + def test_other_loop_future(self): other_loop = asyncio.new_event_loop() fut = self.new_future(other_loop) diff --git a/Misc/NEWS.d/next/Library/2017-08-01-09-32-58.bpo-31061.husAYX.rst b/Misc/NEWS.d/next/Library/2017-08-01-09-32-58.bpo-31061.husAYX.rst new file mode 100644 index 00000000000000..650e5f95f94567 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-08-01-09-32-58.bpo-31061.husAYX.rst @@ -0,0 +1 @@ +Fixed a crash when using asyncio and threads. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index b998a04e623cad..d4b313480e9a10 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -972,6 +972,8 @@ FutureObj_dealloc(PyObject *self) } } + PyObject_GC_UnTrack(self); + if (fut->fut_weakreflist != NULL) { PyObject_ClearWeakRefs(self); } @@ -1846,6 +1848,8 @@ TaskObj_dealloc(PyObject *self) } } + PyObject_GC_UnTrack(self); + if (task->task_weakreflist != NULL) { PyObject_ClearWeakRefs(self); }
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: