Message291763
How to reproduce: Run the following program:
=========================
import asyncio
async def handle_connection(reader, writer):
try:
await reader.readexactly(42)
except BaseException as err:
print('Interesting: %r.' % err)
raise
finally:
writer.close()
loop = asyncio.get_event_loop()
coro = asyncio.start_server(handle_connection, '127.0.0.1', 8888)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
print('KeyboardInterrupt catched.')
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
=========================
0. Python 3.5.2
1. Connect using telnet to localhost and port 888, type one short line and press Enter.
2. Type Ctrl+C in terminal where programw is running.
3. You will see the following output:
=========================
^CKeyboardInterrupt catched.
Interesting: GeneratorExit().
Exception ignored in: <coroutine object handle_connection at 0x7fa6a1d91b48>
Traceback (most recent call last):
File "bug.py", line 12, in handle_connection
writer.close()
File "/usr/lib/python3.5/asyncio/streams.py", line 306, in close
return self._transport.close()
File "/usr/lib/python3.5/asyncio/selector_events.py", line 591, in close
self._loop.call_soon(self._call_connection_lost, None)
File "/usr/lib/python3.5/asyncio/base_events.py", line 567, in call_soon
handle = self._call_soon(callback, args)
File "/usr/lib/python3.5/asyncio/base_events.py", line 576, in _call_soon
self._check_closed()
File "/usr/lib/python3.5/asyncio/base_events.py", line 356, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Task was destroyed but it is pending!
task: <Task pending coro=<handle_connection() done, defined at bug.py:4> wait_for=<Future pending cb=[Task._wakeup()]>>
=========================
This is almost canonical example of asyncio usage. So I have two questions:
1. Why coroutine is interrupted with GeneratorExit instead of CancelledError ?
2. Why something happend AFTER io loop is closed ?
3. How to code all that right ? I want to close connection on any error. Example provided is simplified code. In real code it looks like:
=====
try:
await asyncio.wait_for(self._handle_connection(reader, writer), 60)
except asyncio.TimeoutError:
writer.transport.abort()
except asyncio.CancelledError:
writer.transport.abort()
except Exception:
writer.transport.abort()
finally:
writer.close()
===== |
|
Date |
User |
Action |
Args |
2017-04-16 18:18:42 | socketpair | set | recipients:
+ socketpair |
2017-04-16 18:18:42 | socketpair | set | messageid: <1492366722.76.0.0689582979435.issue30083@psf.upfronthosting.co.za> |
2017-04-16 18:18:42 | socketpair | link | issue30083 messages |
2017-04-16 18:18:42 | socketpair | create | |
|