I have a small HTTP server written using gevent that accepts incoming connections and sends back data using a per-connection greenlet. When the (local) client dies server-side writes to the client succeed despite the socket being in the CLOSE_WAIT state:
$ ls -l /proc/21860/fd |grep 22
lrwx------. 1 mathieu mathieu 64 Mar 21 19:55 22 -> socket:[187093]
$ lsof |grep 187093
python 21860 mathieu 22u IPv4 187093 0t0 TCP localhost.localdomain:36072->localhost.localdomain:48908 (CLOSE_WAIT)
Now, I would expect the send method of the socket I created with gevent.socket.socket to fail with an exception but I get none !
def send(socket, data):
sent = socket.send(data)
while sent != len(data):
data = data[sent:]
sent = socket.send(data)
Is my expectation incorrect ? If not, what could be going wrong here ?
After a bit of debugging, it turns out that my expectation about how the socket API behaves on top of TCP was incorrect. Potential readers might want to read carefully TCP option SO_LINGER (zero) - when it's required
Things to take away:
To sum it up, it means that my server needs to use the end-of-stream notification returned as recv() == 0 as a sign that the client has closed its connection and act accordingly (that is, close the associated socket).