Skip to content

Commit

Permalink
Fix cases in Session.request method where an exception could lead to …
Browse files Browse the repository at this point in the history
…exiting the method without the created socket being owned by a response or closed. This would then cause future calls to get a socket with the same parameters to fail because one already existed and hadn't been closed. The PR #72 fixed this issue for one case where an exception could be raised. This generalizes that in an attempt to fix it in other cases that could still be hit.
  • Loading branch information
aggieNick02 committed Sep 27, 2024
1 parent 2db92cd commit 211e7cf
Showing 1 changed file with 20 additions and 10 deletions.
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

0 comments on commit 211e7cf

Please sign in to comment.