Closed
Description
- uvloop version: 0.14.0, reproducible on master (35f8250)
- Python version: 3.8
- Platform: Linux
- Can you reproduce the bug with
PYTHONASYNCIODEBUG
in env?: Yes - Does uvloop behave differently from vanilla asyncio? How?: Yes:
import asyncio
import contextvars
import aiohttp
import aiohttp.web
import uvloop
var = contextvars.ContextVar('uvloop is awesome', default=None)
async def handle(request):
assert var.get() is not None
return aiohttp.web.Response(text='OK!')
async def client():
await asyncio.sleep(1)
async with aiohttp.ClientSession() as session:
async with session.get('http://localhost:12345/') as response:
text = await response.text()
assert text == 'OK!'
async def setup(app):
var.set('It truly is!')
async def create_app():
app = aiohttp.web.Application()
app.on_startup.append(setup)
app.add_routes([aiohttp.web.get('/', handle)])
asyncio.create_task(client())
return app
if __name__ == '__main__':
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
aiohttp.web.run_app(create_app(), port=12345)
Code works as expected on asyncio loop (var
has value in handler) but fails with uvloop. I tracked difference up to connection_made()
:
File "uvloop/cbhandles.pyx", line 73, in uvloop.loop.Handle._run
File "uvloop/handles/tcp.pyx", line 153, in uvloop.loop.TCPTransport._call_connection_made
File "uvloop/handles/basetransport.pyx", line 134, in uvloop.loop.UVBaseTransport._call_connection_made
File "uvloop/handles/basetransport.pyx", line 131, in uvloop.loop.UVBaseTransport._call_connection_made
File "aiohttp/web_protocol.py", line 223, in connection_made
There is similar difference in UVStreamHandler._on_listen
:
uvloop/uvloop/handles/streamserver.pyx
Line 67 in 35f8250
protocol_handler()
is being called without context activation, while with asyncio it receives context. I'm not sure if this can be the root cause.