Repository navigation
ReadTimeout - SSL shutdown timed out #1008
Description
Hi,
Just curious if someone might have some insight as to what might be happening here. I have some code that is subscribing to messages via an SSE server. The code is very similar to this:
import asyncio
import httpx
client = httpx.AsyncClient()
async def sse():
async with client:
async with client.stream('GET', 'https://server.blargh.home:5000/stream', timeout=None) as response:
async for chunk in response.aiter_raw():
yield chunk
async def subscribe():
async for event in sse():
print(repr(event))
asyncio.run(subscribe())On one device in particular, about 40% of the time, I'm seeing that httpcore._exceptions.ReadTimeout is raised from the aiter_raw(). Here is the traceback:
async for chunk in response.aiter_raw():
async for chunk in self.aiterator:
async for chunk in self.stream:
async for part in self._raw_stream:
File "/usr/local/packages/python3_7_acap/python3.7/lib/python3.7/site-packages/httpcore/_async/base.py", line 57, in __aiter__
File "/usr/local/packages/python3_7_acap/python3.7/lib/python3.7/site-packages/httpcore/_async/connection_pool.py", line 49, in __aiter__
File "/usr/local/packages/python3_7_acap/python3.7/lib/python3.7/site-packages/httpx/_models.py", line 1009, in aiter_raw
File "/usr/local/packages/python3_7_acap/python3.7/lib/python3.7/site-packages/pygw/core/client.py", line 175, in sse
ERROR: Other SSE failure.
Traceback (most recent call last):
data = await self.socket.read(self.READ_NUM_BYTES, timeout)
event = await self._receive_event(timeout)
raise to_exc(exc) from None
self.stream_reader.read(n), timeout.get("read")
File "/usr/local/packages/python3_7_acap/python3.7/lib/python3.7/site-packages/httpcore/_async/http11.py", line 128, in _receive_response_data
File "/usr/local/packages/python3_7_acap/python3.7/lib/python3.7/site-packages/httpcore/_async/http11.py", line 145, in _receive_event
File "/usr/local/packages/python3_7_acap/python3.7/lib/python3.7/site-packages/httpcore/_backends/asyncio.py", line 135, in read
File "/usr/local/packages/python3_7_acap/python3.7/lib/python3.7/site-packages/httpcore/_exceptions.py", line 12, in map_exceptions
File "<pyrun>/contextlib.py", line 130, in __exit__
httpcore._exceptions.ReadTimeout: SSL shutdown timed out
The stream is pretty dead. Every ~ 5 minutes a heartbeat is sent but otherwise it is generally quiet. This problem is only happening on one device and it happens to be running PyRun as its interpreter. Perhaps that's making some difference.
As it is, I have a try/except around the async with client so the stream is able to be re-established and works. Just trying to figure out what might be generating this and if there's some system configuration that needs to be done, or...
Thank you for any help!
Activity
yeraydiazdiaz commentedon May 30, 2020
Hi @ScottSturdivant,
Can you clarify what you mean by that?
In the meantime it'd be useful if you could set and environment variable
HTTPX_LOG_LEVELtoTRACEto get some further logging as described in the docs.Moving to httpx until we know for a fact that it's an issue in httpcore.
ScottSturdivant commentedon May 30, 2020
Hi @yeraydiazdiaz,
Thanks a lot for taking the time to look at this! Re: 40%, what I mean is that it's not 100% reproducible. Majority (60%) of the time when I run the program, I never receive the
ReadTimeoutexception.During the SSE event handling, I will use the same
AsyncClientinstance that I'm using for the SSE stream itself. Is that perhaps an issue?Here are the logs. It may be a bit tricky to see, but I receive 2 events. (Look for
Yielding event). The first one I do nothing with. The second one, I wind up first submitting aPUTrequest and then aPOSTrequest, using the same client obj. After that point, theReadTimeouterror is raised.yeraydiazdiaz commentedon Jun 2, 2020
Hey, thanks for the trace logs.
So just before the end there's this very odd line:
Which suggests a connection is closed on the client side before sending the body.
In above lines we can see data being sent and received, although it's hard for me to see if there's anything missing from just the size of the payloads. In any case seems the PUT and POST connections both complete with lines like:
So I'm not really sure which connection it is that's being closed while waiting for the request body.
I've tried reproducing it by several requests with binary payloads ~simultaneously to a local HTTPS server but HTTPX behaved as expected for me.
My only suggestion is to wait for encode/httpcore#101 and encode/httpcore#102 to be merged which add more logging to the connection pool, run it again and check the more detailed output.
ScottSturdivant commentedon Jun 2, 2020
Hi @yeraydiazdiaz:
For what it's worth, I've switched to instantiating separate clients for the SSE listener and for the handler and since having done that, have not seen this error.
So my code now looks more like this:
The client for
subscribeis shared with the rest of the app to hopefully take advantage of connection pooling, etc. Just now thessefunction gets its own and the code runs without complaint.I'll keep an eye out on those two issues, but in the meantime closing this one. Thank you again!