Repository navigation
Closed
Labels
Description
- uvloop version: 0.14.0, reproducible on master (35f8250)
- Python version: 3.8
- Platform: Linux
- Can you reproduce the bug with
PYTHONASYNCIODEBUGin 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 = self.protocol_factory() |
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.
Activity
versusvoid commentedon Dec 18, 2019
Context not being restored for protocol_factory call is what causing problems. python's asyncio copies current context (by creating callback handle) when creating
listen()handler:https://github.com/python/cpython/blob/fa919fdf2583bdfead1df00e842f24f30b2a34bf/Lib/asyncio/selector_events.py#L252
uvloop simply calls
UVStreamHandler._on_listenfrom libuv1st1 commentedon Jan 14, 2020
Yes, this is a bug.
1st1 commentedon Mar 17, 2020
This PR needs to be considered as part of this issue, basically #306
Add context support in UVHandle and children
Restore context on listen in UVStreamServer. Fix MagicStack#305
Restore context on listen in UVStreamServer. Fix MagicStack#305
Restore context on listen in UVStreamServer. Fix MagicStack#305
Restore context on listen in UVStreamServer. Fix MagicStack#305