python / python/cpython

`asyncio` does not set `TCP_NODELAY` on macOS

Aberta
#148,783 0 comentários 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

stdlib type-bug
Linguagem predominante
Python
Estrelas
77.2k
Forks
35.9k
Métricas de merge de PRs
Métricas de PR pendentes

Descrição

Bug report

Bug description:

On macOS, asyncio server silently skips setting TCP_NODELAY on accepted connections.

Reproduce
import asyncio
import socket

async def main():
    async def on_connect(reader, writer):
        sock = writer.transport.get_extra_info('socket')
        nodelay = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY)
        print(f'server side: sock.proto={sock.proto} TCP_NODELAY={nodelay}')
        writer.close()
        await writer.wait_closed()
        srv.close()

    srv = await asyncio.start_server(on_connect, '127.0.0.1', 0)
    port = srv.sockets[0].getsockname()[1]

    reader, writer = await asyncio.open_connection('127.0.0.1', port)
    sock = writer.transport.get_extra_info('socket')
    nodelay = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY)
    print(f'client side: sock.proto={sock.proto} TCP_NODELAY={nodelay}')

    await asyncio.sleep(0.1)
    writer.close()
    await writer.wait_closed()
    await srv.wait_closed()

asyncio.run(main())
Platform Side sock.proto TCP_NODELAY
Linux client 6 ✅ 1 ✅
Linux server 6 ✅ 1 ✅
macOS client 6 ✅ 4 ✅
macOS server 0 ❌ 0 ❌

Cause

In socket.__init__, CPython tries to detect proto with getsockopt + SO_PROTOCOL and falls back to 0 if SO_PROTOCOL is not supported, which is the case on macOS.

https://github.com/python/cpython/blob/82767780f8de2fc492567ceb6a590101ae3b19ad/Modules/socketmodule.c#L5749-L5764

While socket.accept does pass in the proto from listening socket, it is silently overridden to zero by the above logic.

https://github.com/python/cpython/blob/82767780f8de2fc492567ceb6a590101ae3b19ad/Lib/socket.py#L300

asyncio sets TCP_NODELAY only when sock.proto == socket.IPPROTO_TCP, but it is 0 on macOS for the above reason.

https://github.com/python/cpython/blob/82767780f8de2fc492567ceb6a590101ae3b19ad/Lib/asyncio/base_events.py#L193-L201

Client socket works fine because no fd is passed to socket.__init__ so the proto detection doesn't happen.

CPython versions tested on:

3.13

Operating systems tested on:

macOS, Linux

Linked PRs
  • gh-148784

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Direção de pesquisa

Revise a implementação vinculada em Modules/socketmodule.c, Lib/socket.py e Lib/asyncio/base_events.py, começando por socket.init e socket.accept. Verifique o PR gh-148784 antes de começar; considera-se concluído quando as conexões aceitas no macOS recebem as informações esperadas do protocolo TCP e o asyncio define TCP_NODELAY de forma consistente com as conexões de cliente.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
c, python
Domínio
networking
Tipo de issue
Bug
Dificuldade
4/5
Tempo estimado
3-5 dias
Status de atividade
Estagnada
Clareza
Claramente especificada
Facilidade para iniciantes
25/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.