[Python-bugs-list] Re: socket left in FIN_WAIT_2 state (PR#108)

clarence@netlojix.com clarence@netlojix.com
Mon, 18 Oct 1999 19:06:26 -0400 (EDT)


> 
> > Using the SocketServer.TCPServer class, the request socket is
> > being left in FIN_WAIT_2 state.  Adding
> > 	request.close()
> > to the end of handle_request fixes it.  I would guess this is
> > actually a deficiency in the __del__ method of the socket object.
> 
> Can you show a small sample program that exhibits this problem?
> (How do I see that a socket is left in FIN_WAIT_2 state???)
> 
> If the problem persists after the Python process has exited,
> I would surmise that the problem is in the kernel -- sockets
> are supposed to be closed when the process exits, aren't they?
> 
> --Guido van Rossum
> 

Hard to show code, but here's a description:
>>> from socket import *
>>> s=socket(AF_INET,SOCK_STREAM)
>>> s.bind('',2001)
>>> s.listen(5)
>>> x=s.accept()
      The connection is established.  The client now closes his end.
      This puts the server-side socket in FIN_WAIT2 state (this is normal).
>>> del x
      This has no effect on the socket state.

>>> x=s.accept()
      Establish another connection, and close the client side.  Again,
      the socket goes to FIN_WAIT2.
>>> x[0].close()
      This leaves the socket in normal TIME_WAIT state, the state of a
      closed connection.

It is true that the kernel will close all of the file descriptors when the
process exits, but sockets are special because of the TCP protocol, and if
they are not closed by the user program, they do not go through the
normal shutdown process.

While sockets in FIN_WAIT2 don't hurt the system (they'll go away eventually),
the reason I thought this is a library problem is that it seems to me that
since the SocketServer code 'created' the socket -- via the accept() --
it should probably close it also when the connection handler returns.  I
imagine there's room for conflicting opinions there, but that seems normal
to me.  It is not mentioned in the documentation whether the handler has
the reponsibility of closing the connection.

I mentioned the __del__ method because it seems that a reclaimed open
socket should have close() applied to it like a function does.  I
see PySocketSock_dealloc() in socketmodule.c, which I would have thought
is the deletion function, does call close(); that should make the above
two cases the same (unless that's not the deletion function).  But somehow
the explicit Python-level close() call is causing a normal shutdown.