Martin Panter <vadmium...@gmail.com> added the comment:

I reproduced the problem on a Windows computer, and now understand why my 
"Content-Length: 0" suggestion isn't good enough on its own. It does solve the 
initial deadlock, but there is a further deadlock. The main thread is waiting 
for the server to shut down while it is holding the HTTP connection open, and 
the server is still trying to read a second request on that connection.

Setting "self.close_connection = True" in the server (or using "Connection: 
close") solves both deadlocks. But it seems cleaner for the client to close the 
connection and response objects anyway, before shutting down the server. I 
would modify the "test_get" method:

with support.captured_stderr() as err:
    self.con.request('GET', '/')
    res = self.con.getresponse()
    res.close()  # Not needed but cleans up socket if no Content-Length
self.con.close()  # Needed to shut down connection with Content-Length

I think my Windows computer has a firewall that holds TCP data if it looks like 
an unfinished HTTP request or response. I suspect Terry and William had a 
similar firewall. Here is a demonstration of the socket behaviour it causes:

>>> from socket import *
>>> listener = socket()
>>> listener.bind(("127.1", 0))
>>> listener.listen()
>>> outgoing = create_connection(listener.getsockname())
>>> [incoming, address] = listener.accept()
>>> outgoing.sendall(b"GET / HTTP/1.1\r\n")  # Unfinished HTTP request
>>> incoming.settimeout(3)
>>> incoming.recv(300)  # Partial request should normally be received
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
socket.timeout: timed out
>>> outgoing.sendall(b"\r\n")  # Complete the request
>>> incoming.recv(300)  # Only now is the request received
b'GET / HTTP/1.1\r\n\r\n'
>>> incoming.sendall(b"HTTP/1.1 200 OK\r\n")  # Unfinished response
>>> outgoing.settimeout(3)
>>> outgoing.recv(300)  # Should normally be received
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
socket.timeout: timed out
>>> incoming.sendall(b"Content-Length: 0\r\n\r\n")  # Complete the response
>>> outgoing.recv(300)  # Only now received
b'HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n'

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue25095>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to