You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Michael Smith <ms...@xn.com.au> on 2001/03/16 04:02:51 UTC

accept() errors

Hi,

My server (tomcat 4.0, nightly built from about a week ago, running on a
linux system) stopped responding some time last night. The logs contain
nothing of substance except this:

java.net.SocketException: Connection reset by peer
        at java.net.PlainSocketImpl.socketAccept(Native Method)
        at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:413)
        at java.net.ServerSocket.implAccept(ServerSocket.java:243)
        at java.net.ServerSocket.accept(ServerSocket.java:222)
        at
org.apache.catalina.connector.http.HttpConnector.run(HttpConnector.java:764)
        at java.lang.Thread.run(Thread.java:484)

So, looking through this, I found that the HttpConnector() just breaks
out of the connect loop when accept() throws a SocketException, after
logging the above message. As a result, the connector stops responding,
so things don't work too well.

So, this is obviously not the best behaviour - a socket exception on
accept is usually not fatal. Unfortunately, java gives us absolutely no
way to find out whether or not it was one of the fatal socket errors.
Most of the time, it's safe to just continue in the main accept loop
here. However, sometimes it's neccesary to close and reopen the socket. 

We don't (can't - java doesn't propogate the info out of the native
methods) know which is the case here. So, it seems we need to
close/reopen the server socket either way - unfortunate, since pending
connections could get dropped, but not too terrible, since accept errors
are fairly rare.

I think the correct thing to do is (in this code from
HttpConnector.java)
	    try {
                socket = serverSocket.accept();
                if (connectionTimeout > 0)
                    socket.setSoTimeout(connectionTimeout);
            } catch (IOException e) {
                if (started && !stopped)
                    log("accept: ", e);
                break;
            }

Change the 'break' to something like:
  serverSocket.close();
  serverSocket = open();
  continue;

I'm not familiar with the tomcat code, though, so I'm not certain this
is correct. Also, this is very difficult to reproduce (it's only
happened once, more or less randomly). Comments? Ideas? People with more
knowledge of low-level socket code?

Michael

Re: accept() errors

Posted by Remy Maucherat <re...@apache.org>.
> Hi,
>
> We don't (can't - java doesn't propogate the info out of the native
> methods) know which is the case here. So, it seems we need to
> close/reopen the server socket either way - unfortunate, since pending
> connections could get dropped, but not too terrible, since accept errors
> are fairly rare.
>
> I think the correct thing to do is (in this code from
> HttpConnector.java)
>     try {
>                 socket = serverSocket.accept();
>                 if (connectionTimeout > 0)
>                     socket.setSoTimeout(connectionTimeout);
>             } catch (IOException e) {
>                 if (started && !stopped)
>                     log("accept: ", e);
>                 break;
>             }
>
> Change the 'break' to something like:
>   serverSocket.close();
>   serverSocket = open();
>   continue;
>
> I'm not familiar with the tomcat code, though, so I'm not certain this
> is correct. Also, this is very difficult to reproduce (it's only
> happened once, more or less randomly). Comments? Ideas? People with more
> knowledge of low-level socket code?

Thanks a lot for finding that problem :-)
Closing and reopening the socket is probably the only clean solution. Unless
someone has a better idea, I'll commit the fix tomorrow.

Remy