asyncio: SSL transport raises AttributeError after close() in connection_lost()

Fermée
#160,964 1 commentaire 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Difficulté
4/5
Temps estimé
3-5 jours
Accessibilité débutants
25/100
Type d'issue
Bug
Clarté
Plutôt claire
Activité
À l'abandon
Stack technique
python
Domaine
networking

Piste de recherche

Start by locating _SSLProtocolTransport.close() and the asyncio SSL transport tests; the issue identifies that method as the source and includes a reproduction. Check the behavior of write(), set_protocol(), get_write_buffer_size(), get_extra_info() and the sendfile() fallback after close; done means these paths no longer raise the reported AttributeError and the fallback reports the expected connection error.

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

Description

stdlib topic-asyncio type-bug

Bug report

If a protocol closes its SSL transport in connection_lost(), which is a common pattern, later calls on the transport fail:

import asyncio
from test.test_asyncio import utils as tu

class Proto(asyncio.Protocol):
    def connection_made(self, tr):
        self.tr = tr
    def connection_lost(self, exc):
        self.tr.close()
        self.lost.set_result(None)

async def main():
    async def handler(reader, writer):
        writer.close()
    srv = await asyncio.start_server(handler, '127.0.0.1', 0,
                                     ssl=tu.simple_server_sslcontext())
    port = srv.sockets[0].getsockname()[1]
    loop = asyncio.get_running_loop()
    proto = Proto()
    proto.lost = loop.create_future()
    tr, _ = await loop.create_connection(
        lambda: proto, '127.0.0.1', port, ssl=tu.simple_client_sslcontext())
    await proto.lost
    tr.write(b'x')  # AttributeError: 'NoneType' object has no attribute '_write_appdata'
    srv.close()

asyncio.run(main())

set_protocol(), get_write_buffer_size() and get_extra_info() fail the same way. Plain TCP transports don't have this problem.

It also breaks the loop.sendfile() fallback over SSL: if the peer disconnects mid-transfer, restore() calls set_protocol() and raises AttributeError instead of the expected connection error.

The cause is in _SSLProtocolTransport.close(). When it's called on a transport already marked closed, it sets _ssl_protocol = None. That was added in gh-98539 so the transport doesn't keep the SSL context alive, but it leaves the transport unusable.

Affects 3.11 and later.

Linked PRs
  • gh-160965
Langage dominant
Python
Étoiles
77.8k
Forks
37.7k
Merge moyen
17 h 24 min
PR mergées (30 j)
716

Préparer son environnement

Ouvrir dans Codespaces

Lance le conteneur de développement du projet dans votre navigateur, avec votre propre compte GitHub.

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 python/cpython

Toutes les issues de python/cpython

Issues similaires

Plus d'issues Python

Recevez les nouvelles issues par e-mail

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