Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asyncio: GeneratorExit + strange exception #74269

Closed
socketpair mannequin opened this issue Apr 16, 2017 · 4 comments
Closed

Asyncio: GeneratorExit + strange exception #74269

socketpair mannequin opened this issue Apr 16, 2017 · 4 comments

Comments

@socketpair
Copy link
Mannequin

socketpair mannequin commented Apr 16, 2017

BPO 30083
Nosy @gsalgado, @socketpair, @1st1

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2017-04-16.18:18:42.735>
labels = ['expert-asyncio']
title = 'Asyncio: GeneratorExit + strange exception'
updated_at = <Date 2020-09-18.10:56:44.670>
user = 'https://github.com/socketpair'

bugs.python.org fields:

activity = <Date 2020-09-18.10:56:44.670>
actor = 'salgado'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['asyncio']
creation = <Date 2017-04-16.18:18:42.735>
creator = 'socketpair'
dependencies = []
files = []
hgrepos = []
issue_num = 30083
keywords = []
message_count = 2.0
messages = ['291763', '377104']
nosy_count = 3.0
nosy_names = ['salgado', 'socketpair', 'yselivanov']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = None
url = 'https://bugs.python.org/issue30083'
versions = ['Python 3.5']

@socketpair
Copy link
Mannequin Author

socketpair mannequin commented Apr 16, 2017

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()

=========================

  1. Python 3.5.2
  2. Connect using telnet to localhost and port 888, type one short line and press Enter.
  3. Type Ctrl+C in terminal where programw is running.
  4. 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()
=====

@socketpair socketpair mannequin added the expert-asyncio label Apr 16, 2017
@gsalgado
Copy link
Mannequin

gsalgado mannequin commented Sep 18, 2020

I've also been affected by this and found that if you use asyncio.run() the coroutine is interrupted with a CancelledError as you'd expect. The following script shows that

=======================

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()

async def main():
    listener = await asyncio.start_server(handle_connection, '127.0.0.1', 8888)
    try:
        async with listener:
            await listener.serve_forever()
    except KeyboardInterrupt:
        print('KeyboardInterrupt')

asyncio.run(main())

=============================================

@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
@kumaraditya303
Copy link
Contributor

Not able to reproduce on main and main has new signal handling which won't be backported so closing.

@kumaraditya303 kumaraditya303 closed this as not planned Won't fix, can't repro, duplicate, stale Sep 9, 2022
@Dreamsorcerer
Copy link
Contributor

The original example doesn't cause any errors for me, even on Python 3.8. But, we see a lot of these errors in aiohttp's test suite and have struggled to track them down:
aio-libs/aiohttp#7196

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

No branches or pull requests

2 participants