Skip to content

anyio.EndOfStream can leak up #808

Closed

Description

@mcclurem

Originally raised on httpx, referred here

Discussed in encode/httpx#2848

When using httpx as follows:

async with httpx.AsyncClient(verify=client.verify_ssl) as _client:
        response = await _client.request(**kwargs)

with a misbehaving server I will occasionally get an anyio.EndOfStream exception thrown from deep in the call stack.
I would expect that this should have been caught by httpx and converted into one of the applicable httpx exceptions (probably one of the StreamErrors)

call stack that I see this in:

File "/lib/python3.10/site-packages/httpx/_client.py", line 1530, in request
    return await self.send(request, auth-auth, follow_redirects-follow_redirects)
File "/lib/python3.10/site-packages/httpx/_client.py", line 1617, in send
    response = await self._send_handling_auth
File "/lib/python3.10/site-packages/httpx/_client.py", line 1645, in _send_handling_auth
    response = await self._send_handling_redirects
File "/Users/rack-user/minion_venv/1ib/python3.10/site-packages/httpx/_client.py", line 1682, in _send_handling_redirects
    response = await self._send_single_request (request)
File "/lib/python3.10/site-packages/httpx/_client.py", line 1719, in _send_single_request
    response = await transport. handle_async_request(request)
File "/Users/rack-user/minion_venv/lib/python3.10/site-packages/httpx/_transports/default.py", line 353, in handle_async_request
    resp = await self._pool.handle_async_request(reg)
File "/lib/python3.10/site-packages/httpcore/_async/connection_pool.py", line 262, in handle_async_request
    raise exc
File "/lib/python3.10/site-packages/httpcore/_async/connection_pool.py", line 245, in handle_async_request
    response = await connection.handle_async_request(request)
File "/lib/python3.10/site-packages/httpcore/_async/connection.py", line 92, in handle_async_request
    raise exc
File "/lib/python3.10/site-packages/httpcore/_async/connection.py", line 69, in handle_async_request
    stream = await self._connect(request)
File "/lib/python3.10/site-packages/httpcore/_async/connection.py", line 149, in _connect
    stream = await stream.start_tls(**kwargs)
File "/Users/rack_user/minion-venv/lib/python3.10/site-packages/httpcore/_backends/anyio.py", line 78, in start_tls
    raise exc
File "/lib/python3.10/site-packages/httpcore/_backends/anyio.py", line 69, in start_tls
ssl_stream = await anyio.streams.tls.TLSStream.wrap(
File "/lib/python3.10/site-packages/anyio/streams/tls.py", line 125, in wrap
    await wrapper._call_sslobject_method(ss1_object.do_handshake)
File "/lib/python3.10/site-packages/anyio/streams/tls.py", line 165, in _call_sslobject_method
    raise EndOfStream from None

Activity

  1. karpetrosyan commented on Sep 19, 2023

    @karpetrosyan
    Contributor

    It seems like we should just add the new exception mapping to the anyio backend module.

    EndOfStream class definition:

    class EndOfStream(Exception):
        """Raised when trying to read from a stream that has been closed from the other end."""

    I believe it would be sufficient to add EndOfStream mapping with ReadError here.

    exc_map = {
    TimeoutError: ConnectTimeout,
    anyio.BrokenResourceError: ConnectError,
    }

    and here

    exc_map = {
    TimeoutError: ReadTimeout,
    anyio.BrokenResourceError: ReadError,
    anyio.ClosedResourceError: ReadError,
    }

  2. lovelydinosaur commented on Sep 19, 2023

    @lovelydinosaur
    Member

    For bonus points...

    • Which exceptions does anyio document may be raised in each circumstance? If a pull request here can reference the anyio docs then we'll have good interlinking, and be confident that we've correctly covered the various possible exception cases. I dug into this from a quick look, but haven't comprehensively listed out which exceptions could be raised from each of our stream operations.
    • Can you demo the issue in the most isolated case possible, by working with just the network backend API? Being able to show a case where the exception is raised just using .connect_tcp() and .start_tls() would show that we've properly isolated the issue. (I know we have, but it'd be a neat wrapping up.) Do our docs properly indicate which exceptions may be raised by the network backend operations?
  3. PrathamSoni commented on Jan 8, 2024

    @PrathamSoni

    Hi! Were there any updates to this?

  4. lovelydinosaur commented on Jan 9, 2024

    @lovelydinosaur
    Member

    This is still up for grabs, pull requests welcome. 🤗

    @karpetrosyan's comment above points to where we need a couple of entries adding in our exception mapping.

  5. jakekaplan commented on Mar 19, 2024

    @jakekaplan

    Really glad to see this issue is closed 🙌!

    Any idea when the next release will be that includes this?

  6. seano314 commented on Mar 27, 2024

    @seano314

    Really glad to see this issue is closed 🙌!

    Any idea when the next release will be that includes this?

    Agree completely and would love to know the answer to this question too :)

  7. lovelydinosaur commented on Mar 27, 2024

    @lovelydinosaur
    Member

    Welcome to issue a release PR.

    For example, see... #892

  8. okba-boularaoui commented on Mar 27, 2024

    @okba-boularaoui
    Contributor

    Thank you @tomchristie, Version 1.0.5 (#904) PR is ready for review.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions