uvicorn closes client connection arbitrarily

Created on 19 Oct 2020  路  3Comments  路  Source: encode/uvicorn

I encountered a race condition where uvicorn closes the connection at random. The problem seems to be incorrect management of the keep-alive timer in uvicorn/protocols/http/httptools_impl.py (HttpToolsProtocol).

Under some conditions, on_response_complete might be called after data has been received for the next request. When this happens, there might be two on_response_complete calls without a data_received call inbetween, hence timeout_keep_alive_task is overridden with a new timer without canceling the old one. When the leaked timer expires, the connection is killed.

Minimal test case:

Server side:

import asyncio

async def app(scope, receive, send):
    m = await receive()

    if m['type'] == 'lifespan.startup':
        await send({'type': 'lifespan.startup.complete'})
    elif m['type'] == 'http.request':
        await asyncio.sleep(.2)
        await send({'type': 'http.response.start', 'status': 200, 'headers': [(b'content-length',b'5')]})
        await send({'type': 'http.response.body', 'body': b'data\n', 'more_body': True})
        await asyncio.sleep(.5)
        await send({'type': 'http.response.body', 'body': b'', 'more_body': False})

Client side:

import requests
import time
s = requests.Session()
for i in range(2):
    s.get(f'http://localhost:8000/{i}')
time.sleep(1)
for i in range(10):
    s.get(f'http://localhost:8000/{i}')
bug

Most helpful comment

Probably I found the solution. Once I write test cases, I'll fire a PR

All 3 comments

@itayperl

The bug is reproducible using your snippet.

Probably yes, the bug related to the fact, that setting new keep-alive task, we do not cancel the old-one

Probably I found the solution. Once I write test cases, I'll fire a PR

As you can see the tests are failing without the fix

https://github.com/encode/uvicorn/pull/831/checks?check_run_id=1298976600

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tarioch picture tarioch  路  4Comments

tomchristie picture tomchristie  路  6Comments

Legionof7 picture Legionof7  路  3Comments

Gyllsdorff picture Gyllsdorff  路  6Comments

tomchristie picture tomchristie  路  4Comments