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

After making a few POST requests with large body and small keep-alive, one of the requests ends with the connection aborted. #2097

Open
wb7777 opened this issue Sep 11, 2023 · 3 comments

Comments

@wb7777
Copy link

wb7777 commented Sep 11, 2023

After making a few POST requests with large body and small keep-alive, one of the requests ends with the connection aborted.
The server said thats all right, but connection is aborted

It seems similar to #1345, but different.

uvicorn: 0.23.2

How to reproduce:

Server side:

# test.py
from starlette.requests import Request
from starlette.responses import Response
from starlette.applications import Starlette
from starlette.routing import Route


async def test(request: Request):
    await request.body()
    return Response()


routes = [
    Route("/test", endpoint=test, methods=['post'])
]

app = Starlette(debug=True, routes=routes)

Uvicorn start:

uvicorn --timeout-keep-alive 1 test:app

Client side:

import asyncio
import aiohttp


should_stop = False


async def worker(session):
    global should_stop

    try:
        async with session.post('http://localhost:8000/test', data='x' * 100_000_000) as response:
            print(f"Status:", response.status)
    except:
        should_stop = True
        raise


async def main():
    async with aiohttp.ClientSession() as session:
        tasks = []
        while not should_stop:
            tasks.append(asyncio.create_task(worker(session)))

            await asyncio.sleep(0)

        done, _ = await asyncio.wait(tasks)

        [x.result() for x in done if x.exception()]


asyncio.run(main())

After several iterations, one of the exceptions occurs:

  File "/Users/wb77/.pyenv/versions/3.11.1/envs/integration.intas.sync/lib/python3.11/site-packages/aiohttp/streams.py", line 616, in read
    await self._waiter
aiohttp.client_exceptions.ClientOSError: [Errno 32] Broken pipe
  File "/Users/wb77/.pyenv/versions/3.11.1/envs/integration.intas.sync/lib/python3.11/site-packages/aiohttp/http_writer.py", line 75, in _write
    raise ConnectionResetError("Cannot write to closing transport")
ConnectionResetError: Cannot write to closing transport

and some another exceptions.

If we increase keep-alive timeout, the frequency of error is reduced.

Originally posted by @wb7777 in #2021

@Kludex
Copy link
Member

Kludex commented Sep 11, 2023

May be related to django/asgiref#66. I'm not sure.

I'll investigate.

@ghost
Copy link

ghost commented Sep 15, 2023

when i run this:

uvicorn  --timeout-keep-alive 1 test:app

and run client script, the first output on client side is:

$ python client.py
killed

server side:

...
starlette.requests.ClientDisconnect

the server still running, so i ran client script again and after some iterations:
(client side output)

...
aiohttp.client_exceptions.ClientOsError [Errno 32] Broken Pipe

@viningz
Copy link

viningz commented Oct 24, 2024

I also encountered this issue. My environment is uvicorn:0.32.0, python:3.11.10. I discovered through tcpdump packet capture that when the server sends out an RST state, the window size is 0.

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

No branches or pull requests

3 participants