Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

UDPTransport.abort() with a queued datagram reports a fatal write error and a resume_writing() AttributeError

Ouverte
#771 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

@graingert y travaille déjà.

Depuis le 5/10/2026.

  • #772 par @graingert — ouverte

Évaluation

Difficulté
3/5
Temps estimé
1-2 jours
Accessibilité débutants
68/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
python
Domaine
networking

Piste de recherche

Start by reproducing the issue with the provided script, then trace UDPTransport.abort() and UVBaseTransport._maybe_resume_protocol to see how queued-send cancellation and protocol detachment interact. Compare the exception-handler output with vanilla asyncio; done means abort discards the queued datagram without reporting either error, while connection_lost(None) still occurs.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

  • uvloop version: 0.23.0 (also 0.22.1)
  • Python version: 3.12.3
  • Platform: Linux (x86_64, glibc 2.39)
  • Can you reproduce the bug with PYTHONASYNCIODEBUG in env?: Yes
  • Does uvloop behave differently from vanilla asyncio? How?: Yes. With vanilla asyncio, abort() silently discards the queued datagram and calls connection_lost(None). With uvloop, connection_lost(None) is called too, but two errors are also passed to the loop's exception handler.

Calling abort() on a UDPTransport while a datagram is still queued (because the OS refused it with EAGAIN) reports two errors to the loop's exception handler:

  1. Fatal error on transport UDPTransport (Fatal write error on datagram transport), with exception=CancelledError(). The queued send is cancelled because we aborted, so this is not an error.
  2. protocol.resume_writing() failed, with AttributeError("'NoneType' object has no attribute 'resume_writing'"), raised from UVBaseTransport._maybe_resume_protocol after the protocol has already been detached.

A UNIX datagram socket is used to make the OS refuse datagrams, because UDP on loopback never exerts back-pressure. The peer never reads, so the send buffer fills up.

import asyncio
import socket
import sys
import tempfile

import uvloop


class Protocol(asyncio.DatagramProtocol):
    def connection_made(self, transport):
        transport.set_write_buffer_limits(0)

    def connection_lost(self, exc):
        print("connection_lost", exc)


async def main():
    loop = asyncio.get_running_loop()
    errors = []
    loop.set_exception_handler(lambda loop, context: errors.append(context))

    path = f"{tempfile.mkdtemp()}/peer.sock"
    peer = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
    peer.bind(path)  # never read from

    sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
    sock.connect(path)
    sock.setblocking(False)
    transport, _ = await loop.create_datagram_endpoint(Protocol, sock=sock)

    # Send until the OS refuses a datagram and the transport has to queue it
    while not transport.get_write_buffer_size():
        transport.sendto(b"x" * 64)

    transport.abort()
    await asyncio.sleep(0.1)
    for context in errors:
        print("exception handler:", context["message"], repr(context.get("exception")))


if sys.argv[1:] == ["uvloop"]:
    uvloop.run(main())
else:
    asyncio.run(main())

Output with python repro.py:

connection_lost None

Output with python repro.py uvloop:

connection_lost None

exception handler: Fatal error on transport UDPTransport (Fatal write error on datagram transport) CancelledError()
exception handler: protocol.resume_writing() failed AttributeError("'NoneType' object has no attribute 'resume_writing'")

Expected: the same as vanilla asyncio, i.e. the queued datagram is silently discarded and nothing is reported to the exception handler.

Found via anyio, whose UDP socket aclose() aborts the transport.

Langage dominant
Cython
Étoiles
11.9k
Forks
616
Merge moyen
4 h 43 min
PR mergées (30 j)
3

Préparer son environnement

Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de MagicStack/uvloop

Toutes les issues de MagicStack/uvloop

Issues similaires

Plus d'issues Networking

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.