summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Svetlov <andrew.svetlov@gmail.com>2019-05-14 16:09:44 (GMT)
committerVictor Stinner <vstinner@redhat.com>2019-05-14 16:09:44 (GMT)
commitf12ba7cd0a7370631214ac0b337ab5455ce717b2 (patch)
tree26b7914a776c311c65cb94cd12ffe409eb4f20a8
parentc96be811fa7da8ddcea18cc7abcae94e0f5ff966 (diff)
downloadcpython-f12ba7cd0a7370631214ac0b337ab5455ce717b2.zip
cpython-f12ba7cd0a7370631214ac0b337ab5455ce717b2.tar.gz
cpython-f12ba7cd0a7370631214ac0b337ab5455ce717b2.tar.bz2
bpo-36916: asyncio: Swallow unhandled write() exception (GH-13313)
-rw-r--r--Lib/asyncio/streams.py11
-rw-r--r--Lib/test/test_asyncio/test_streams.py3
-rw-r--r--Misc/NEWS.d/next/Library/2019-05-14-15-39-34.bpo-36916._GPsTt.rst2
3 files changed, 15 insertions, 1 deletions
diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py
index d9a9f5e..146a338 100644
--- a/Lib/asyncio/streams.py
+++ b/Lib/asyncio/streams.py
@@ -329,6 +329,13 @@ class StreamReaderProtocol(FlowControlMixin, protocols.Protocol):
closed.exception()
+def _swallow_unhandled_exception(task):
+ # Do a trick to suppress unhandled exception
+ # if stream.write() was used without await and
+ # stream.drain() was paused and resumed with an exception
+ task.exception()
+
+
class StreamWriter:
"""Wraps a Transport.
@@ -393,7 +400,9 @@ class StreamWriter:
# fast path, the stream is not paused
# no need to wait for resume signal
return self._complete_fut
- return self._loop.create_task(self.drain())
+ ret = self._loop.create_task(self.drain())
+ ret.add_done_callback(_swallow_unhandled_exception)
+ return ret
def write_eof(self):
return self._transport.write_eof()
diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py
index bf93f30..8d6a1d2 100644
--- a/Lib/test/test_asyncio/test_streams.py
+++ b/Lib/test/test_asyncio/test_streams.py
@@ -851,6 +851,8 @@ os.close(fd)
# where it never gives up the event loop but the socket is
# closed on the server side.
+ messages = []
+ self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx))
q = queue.Queue()
def server():
@@ -883,6 +885,7 @@ os.close(fd)
# Clean up the thread. (Only on success; on failure, it may
# be stuck in accept().)
thread.join()
+ self.assertEqual([], messages)
def test___repr__(self):
stream = asyncio.StreamReader(loop=self.loop,
diff --git a/Misc/NEWS.d/next/Library/2019-05-14-15-39-34.bpo-36916._GPsTt.rst b/Misc/NEWS.d/next/Library/2019-05-14-15-39-34.bpo-36916._GPsTt.rst
new file mode 100644
index 0000000..8726bb2
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-05-14-15-39-34.bpo-36916._GPsTt.rst
@@ -0,0 +1,2 @@
+Remove a message about an unhandled exception in a task when writer.write()
+is used without await and writer.drain() fails with an exception.