python / python/cpython

`asyncio` does not set `TCP_NODELAY` on macOS

Offen
#148,783 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

stdlib type-bug
Vorherrschende Sprache
Python
Sterne
77.2k
Forks
35.9k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

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

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Überprüfe die verknüpfte Implementierung in Modules/socketmodule.c, Lib/socket.py und Lib/asyncio/base_events.py, beginnend mit socket.init und socket.accept. Prüfe vor Beginn PR gh-148784; abgeschlossen ist die Aufgabe, wenn akzeptierte macOS-Verbindungen die erwarteten TCP-Protokollinformationen erhalten und asyncio TCP_NODELAY konsistent mit Clientverbindungen setzt.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
c, python
Bereich
networking
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
25/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.