summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorINADA Naoki <methane@users.noreply.github.com>2017-08-02 07:50:39 (GMT)
committerGitHub <noreply@github.com>2017-08-02 07:50:39 (GMT)
commitf142e85d22ba135d5205280240f3a2fe1df2649f (patch)
tree32e45abe96a96edf8fb36ecf60588385a1764a16
parent48fcc72c83e1b47b200dd39f9dcc9f62fa0d4d17 (diff)
downloadcpython-f142e85d22ba135d5205280240f3a2fe1df2649f.zip
cpython-f142e85d22ba135d5205280240f3a2fe1df2649f.tar.gz
cpython-f142e85d22ba135d5205280240f3a2fe1df2649f.tar.bz2
bpo-31061: fix crash in asyncio speedup module (GH-2984)
(cherry picked from commit de34cbe9cdaaf7b85fed86f99c2fd071e1a7b1d2)
-rw-r--r--Lib/test/test_asyncio/test_futures.py12
-rw-r--r--Lib/test/test_asyncio/test_tasks.py15
-rw-r--r--Misc/NEWS.d/next/Library/2017-08-01-09-32-58.bpo-31061.husAYX.rst1
-rw-r--r--Modules/_asynciomodule.c4
4 files changed, 32 insertions, 0 deletions
diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py
index ce657fc..ebedfec 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 @@ except ImportError:
def _fakefunc(f):
return f
+
def first_cb():
pass
+
def last_cb():
pass
@@ -483,6 +486,15 @@ class BaseFutureTests:
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 195a1ed..243faf6 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
@@ -92,6 +93,20 @@ class BaseTaskTests:
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 0000000..650e5f9
--- /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 8fbd565..c48cbbc 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -971,6 +971,8 @@ FutureObj_dealloc(PyObject *self)
}
}
+ PyObject_GC_UnTrack(self);
+
if (fut->fut_weakreflist != NULL) {
PyObject_ClearWeakRefs(self);
}
@@ -1845,6 +1847,8 @@ TaskObj_dealloc(PyObject *self)
}
}
+ PyObject_GC_UnTrack(self);
+
if (task->task_weakreflist != NULL) {
PyObject_ClearWeakRefs(self);
}