Skip to content

Asyncio StreamReader fails to close Transport #78357

Description

@jdlh
mannequin
BPO 34176
Nosy @asvetlov, @1st1, @JDLH

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2018-07-21.00:30:19.386>
labels = ['type-bug', '3.7', 'expert-asyncio']
title = 'Asyncio StreamReader fails to close Transport'
updated_at = <Date 2018-07-21.00:30:19.386>
user = 'https://github.com/JDLH'

bugs.python.org fields:

activity = <Date 2018-07-21.00:30:19.386>
actor = 'JDLH'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['asyncio']
creation = <Date 2018-07-21.00:30:19.386>
creator = 'JDLH'
dependencies = []
files = []
hgrepos = []
issue_num = 34176
keywords = []
message_count = 1.0
messages = ['322047']
nosy_count = 3.0
nosy_names = ['asvetlov', 'yselivanov', 'JDLH']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue34176'
versions = ['Python 3.7']

Activity

  1. jdlh commented on Jul 21, 2018

    jdlhmannequin
    MannequinAuthor

    Asyncio's StreamReaderProtocol[1] often returns True from Protocol.eof_received(). This tells the Transport that "closing the transport is up to the protocol" [2]. However, StreamReaderProtocol does not call Transport.close(). More precisely, StreamReaderProtocol leaves the transport interaction to StreamReader. It calls StreamReader.feed_eof()[3]. But StreamReader does not call self._transport.close(). It only sets a self._eof flag, and awakens any of its functions which were waiting for data.

    The only occurrence of self._transport.close() occurs in StreamWriter[4]. There is none in StreamReader or StreamReaderProtocol.

    I believe that the fix should be for StreamReader to call self._transport.close(). However, it may need to avoid this if StreamReaderProtocol._over_ssl is True, and I don't immediately see how it can tell this. Also, it may need to wait for anything waiting for self._waiter to run, before closing the Transport.
    Or, maybe StreamReaderProtocol should not return True from Protocol.eof_received().

    I discovered this when using a Transport of my own devising, which reads from a file instead of from a socket, with asyncio.streams. The file did not close in the unit test. My transport duly called Protocol.eof_received(), but received a True in response, so did not close the file.

    My workaround will probably be to not believe what Protocol.eof_received() tells me, and to close my transport regardless.

    [1] Lib/asyncio.streams.StreamReaderProtocol.eof_received, line 259-266.
    [2] 19.5.4.2.3. "Streaming protocols" <https://docs.python.org/3/library/asyncio-protocol.html\>
    [3] Lib/Lib/asyncio.streams.StreamReader.feed_eof, lines 419-421.
    [4] Lib/Lib/asyncio.streams.StreamWriter.close, lines 316-317.

    All line numbers are as of tag v3.7.0, commit 1bf9cc5 .

    Bug observed in v3.7.0. Not yet investigated in HEAD revision.

  2. transferred this issue fromon Apr 10, 2022
  3. kumaraditya303 commented on May 31, 2022

    @kumaraditya303
    Contributor

    Python 3.7 is not supported anymore, moreover the issue does not has a reproducer to reproduce the issue and is out of date so closing. If this issue still exists, create a new issue with reproducer.

  4. kumaraditya303 commented on May 31, 2022

    @kumaraditya303
    Contributor

    Also 3.11 has rewritten ssl implementation as of #31275.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions