Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

_SelectorSocketTransport.writelines does not protect against connection lost #136234

Labels
3.13bugs and security fixes3.14bugs and security fixes3.15new features, bugs and security fixesstdlibPython modules in the Lib dirtopic-asynciotype-bugAn unexpected behavior, bug, or error
@bmerry

Description

@bmerry

Bug report

Bug description:

SelectorSocketTransport (in asyncio.selector_events) implements bothwrite andwritelines, but only the first has handling for the case that the connection has already been lost. That in turn can lead to dereferencing a None object, because_call_connection_lost clears a number of attributes. Even if that were fixed, it also means that there would be inconsistent behaviour betweenwrite andwritelines (write would drop the data on the floor and possibly print a warning, whilewritelines would append it to the buffer).

I would suggest modifyingwritelines to use the same check for_conn_lost aswrite. Let me know if you'd like a PR.

The code below gives either anAttributeError orTypeError (depending on Python version) on my machine (Ubuntu 24.04, 6.8.0-63-generic). It may depend on corner cases of when exactly the kernel notifies a TCP sender that the other side has closed the connection and hence might not be a totally reliable reproducer.

#!/usr/bin/env python3importasyncioimportfunctoolsasyncdefclient_connected_cb(event:asyncio.Event,reader:asyncio.StreamReader,writer:asyncio.StreamWriter)->None:awaitevent.wait()# Waits for the client side to disconnectwriter.write(b"foo")writer.write(b"spam")# Linux seems to fail the second write but not the firstawaitasyncio.sleep(0)print(writer.transport._conn_lost)# Should be 1writer.writelines([b"baz"])# Replace above line with this for comparison:# writer.write(b"baz")awaitwriter.drain()writer.close()awaitwriter.wait_closed()asyncdefmain():event=asyncio.Event()server=awaitasyncio.start_server(functools.partial(client_connected_cb,event),host="127.0.0.1",port=8888,    )# Establish a connection, then close itclient_reader,client_writer=awaitasyncio.open_connection("127.0.0.1",8888)client_writer.close()awaitclient_writer.wait_closed()event.set()# Wake up client_connected_cb# Cleanupserver.close()awaitserver.wait_closed()if__name__=="__main__":asyncio.run(main())

Output (3.12):

1Unhandled exception in client_connected_cbtransport: <_SelectorSocketTransport closed fd=8>Traceback (most recent call last):  File "/home/bmerry/work/experiments/asyncio-writelines/./writelines_hang.py", line 13, in client_connected_cb    writer.writelines([b"baz"])  File "/usr/lib/python3.12/asyncio/streams.py", line 349, in writelines    self._transport.writelines(data)  File "/usr/lib/python3.12/asyncio/selector_events.py", line 1185, in writelines    self._loop._add_writer(self._sock_fd, self._write_ready)    ^^^^^^^^^^^^^^^^^^^^^^AttributeError: 'NoneType' object has no attribute '_add_writer'

Output (3.13, 3.14):

1Unhandled exception in client_connected_cbtransport: <_SelectorSocketTransport closed fd=8>Traceback (most recent call last):  File "/home/bmerry/work/experiments/asyncio-writelines/./writelines_hang.py", line 13, in client_connected_cb    writer.writelines([b"baz"])    ~~~~~~~~~~~~~~~~~^^^^^^^^^^  File "/home/bmerry/.pyenv/versions/3.14-dev/lib/python3.14/asyncio/streams.py", line 343, in writelines    self._transport.writelines(data)    ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^  File "/home/bmerry/.pyenv/versions/3.14-dev/lib/python3.14/asyncio/selector_events.py", line 1178, in writelines    self._write_ready()    ~~~~~~~~~~~~~~~~~^^TypeError: 'NoneType' object is not callable

Note that 3.11 and earlier are not affected because they do not implementwritelines in SelectorSocketTransport; they rely on the generic version that just concatenates the messages and passes them towrite.

CPython versions tested on:

3.13, 3.14, 3.12

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.13bugs and security fixes3.14bugs and security fixes3.15new features, bugs and security fixesstdlibPython modules in the Lib dirtopic-asynciotype-bugAn unexpected behavior, bug, or error

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp