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

guido@CNRI.Reston.VA.US guido@CNRI.Reston.VA.US
Tue, 19 Oct 1999 01:01:55 -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?
> 
> 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.

I tried to reproduce this, and didn't succeed.  The socket is left in
TIME_WAIT state the first time too.

My guess is that you are being fooled by reference counts and the "_"
variable with this example.  If you typed x at the >>> prompt just
before you did "del x", the _ builtin variable holds a reference to
the object.  This goes away when you display the value of some other
value (e.g. 0, but not None).

> 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.

That is indeed the correct function.

The question now remains, why do you observe this behavior in
SocketServer?  I still want to see the code you are actually using --
maybe there's a clue there.  If not, I'll have to close this PR as
irreproducible...

--Guido van Rossum (home page: http://www.python.org/~guido/)