-
-
Notifications
You must be signed in to change notification settings - Fork 33.2k
Description
Description
While reviewing the close
method in (
Lines 1015 to 1028 in 5e73ece
def close(self): | |
"""Close the connection to the HTTP server.""" | |
self.__state = _CS_IDLE | |
try: | |
sock = self.sock | |
if sock: | |
self.sock = None | |
sock.close() # close it manually... there may be other refs | |
finally: | |
response = self.__response | |
if response: | |
self.__response = None | |
response.close() | |
close()
(line 1022), without first calling shutdown()
.
This is similar to what I previously reported in issue #130850, where _close_self_pipe
in asyncio.selector_events
also closes sockets without calling shutdown()
first.
Code Reference
Currently, the code is as follows:
def close(self):
"""Close the connection to the HTTP server."""
self.__state = _CS_IDLE
try:
sock = self.sock
if sock:
self.sock = None
sock.close() # close it manually... there may be other refs
finally:
response = self.__response
if response:
self.__response = None
response.close()
Question
Would there be any potential downsides or benefits to adding a shutdown(socket.SHUT_RDWR) call before close() in this case?
Possible Benefits
- Ensures that all pending data is properly discarded before closing, particularly in scenarios where data might still be buffered.
- Prevents potential issues with lingering resources in some edge cases.
- Aligns with best practices for socket cleanup.
- Can help avoid RST (reset by peer) issues in some network conditions.
Possible Change
def close(self):
"""Close the connection to the HTTP server."""
self.__state = _CS_IDLE
try:
sock = self.sock
if sock:
self.sock = None
try:
sock.shutdown(socket.SHUT_RDWR) # Gracefully terminate the connection
except OSError:
pass # Ignore errors if the socket is already closed
sock.close() # Close it manually... there may be other refs
finally:
response = self.__response
if response:
self.__response = None
response.close()
Reference
The Python socket documentation states:
"close() releases the resource associated with a connection but does not necessarily close the connection immediately. If you want to close the connection in a timely fashion, call shutdown() before close()."
π Python socket documentation
Since a similar discussion is happening in #130850, I wanted to bring attention to this case in http.client as well.
Looking forward to your thoughts!