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

AsyncServer.start_background_task fails on aiohttp 3.8 #881

Closed
ezio-melotti opened this issue Feb 27, 2022 · 6 comments
Closed

AsyncServer.start_background_task fails on aiohttp 3.8 #881

ezio-melotti opened this issue Feb 27, 2022 · 6 comments
Labels

Comments

@ezio-melotti
Copy link
Contributor

When running AsyncServer.start_background_task on aiohttp 3.8 (both 3.8.0 or 3.8.1), the server fails with a RuntimeWarning: coroutine 'background_task' was never awaited error, but the same code works fine on 3.7.4.

This is a minimal reproducer based on the example in the repo:

import socketio

from aiohttp import web

sio = socketio.AsyncServer(async_mode='aiohttp')
app = web.Application()
sio.attach(app)

async def background_task():
    print('background_task called', flush=True)
    while True:
        print('emitting test-event and sleeping 1s...')
        await sio.emit('test-event', 'test')
        await sio.sleep(1)

if __name__ == '__main__':
    sio.start_background_task(background_task)
    web.run_app(app)

After installing aiohttp 3.7.4 with pip install aiohttp==3.7.4, the server works and the output is:

# python3 bgtask.py 
background_task called
emitting test-event and sleeping 1s...
======== Running on http://0.0.0.0:8080 ========
(Press CTRL+C to quit)
emitting test-event and sleeping 1s...

After installing aiohttp 3.8.1 with pip install aiohttp==3.8.1, the server fails with the output:

# python3 bgtask.py 
/usr/local/lib/python3.9/abc.py:123: RuntimeWarning: coroutine 'background_task' was never awaited
  return _abc_subclasscheck(cls, subclass)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Task was destroyed but it is pending!
task: <Task pending name='Task-1' coro=<background_task() running at /bgtask.py:9>>
======== Running on http://0.0.0.0:8080 ========
(Press CTRL+C to quit)

I'm not sure if this is an issue with python-socketio or a bug in aiohttp itself. Regardless, I thought it would be useful to report it here since other python-socketio users might run in the same problem.

aiohttp 3.8 might have introduced a backward incompatible change that requires an update to python-socketio. If you can verify that this is indeed an issue with aiohttp, and possibly even figure out the cause of the problem, we can then report it upstream.

This was tested with python-socketio 5.5.2 on Python 3.9.10.

@miguelgrinberg
Copy link
Owner

miguelgrinberg commented Feb 28, 2022

Have you considered that this might be your own issue? You are launching an async function before the web framework, which controls the async loop. More than likely aiohttp is creating their own loop, so the default loop used when you started the task goes away and that causes the message that you are seeing.

@ezio-melotti
Copy link
Contributor Author

Thanks for the quick reply! That might explain why it's not working, however there are still three issues:

  • web.run_app(app) is blocking, so the start_background_task call can't be moved afterwards.
  • The same code work fine with aiohttp 3.7, so either python-socketio is not compatible with 3.8 and should be updated, or 3.8 introduced a bug that they should fix.
  • If it's not a bug with 3.8, the example I followed for the reproducer is no longer valid for 3.8 and should be updated.

@miguelgrinberg
Copy link
Owner

Yes, I agree, that example needs to be updated so that it is compatible with the newer aiohttp. I'll look into that.

@miguelgrinberg
Copy link
Owner

This is actually the change in aiohttp that relates to this: aio-libs/aiohttp#5572

@miguelgrinberg
Copy link
Owner

The solution is to use an application factory function to start the background task:

async def init_app():
    sio.start_background_task(background_task)
    return app

if __name__ == '__main__':
    web.run_app(init_app())

@ezio-melotti
Copy link
Contributor Author

Thanks! I verified that this solution works with aiohttp version 3.8.1, 3.8.0, and 3.7.4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants