Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for exceptions in Session.request leading to sockets not properly closed #205

Merged
merged 2 commits into from
Oct 1, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions adafruit_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,10 @@ def request( # noqa: PLR0912,PLR0913,PLR0915 Too many branches,Too many argumen

# We may fail to send the request if the socket we got is closed already. So, try a second
# time in that case.
# Note that the loop below actually tries a second time in other failure cases too,
# namely timeout and no data from socket. This was not covered in the stated intent of the
# commit that introduced the loop, but removing the retry from those cases could prove
# problematic to callers that now depend on that resiliency.
retry_count = 0
last_exc = None
while retry_count < 2:
Expand All @@ -643,17 +647,23 @@ def request( # noqa: PLR0912,PLR0913,PLR0915 Too many branches,Too many argumen
if ok:
# Read the H of "HTTP/1.1" to make sure the socket is alive. send can appear to work
# even when the socket is closed.
if hasattr(socket, "recv"):
result = socket.recv(1)
else:
result = bytearray(1)
try:
# Both recv/recv_into can raise OSError; when that happens, we need to call
# _connection_manager.close_socket(socket) or future calls to
# _connection_manager.get_socket() for the same parameter set will fail
try:
if hasattr(socket, "recv"):
result = socket.recv(1)
else:
result = bytearray(1)
socket.recv_into(result)
except OSError:
pass
if result == b"H":
# Things seem to be ok so break with socket set.
break
if result == b"H":
# Things seem to be ok so break with socket set.
break
else:
raise RuntimeError("no data from socket")
except (OSError, RuntimeError) as exc:
last_exc = exc
pass
self._connection_manager.close_socket(socket)
socket = None

Expand Down