Bug 56416

Summary: HTTP NIO connector: SocketExceptions and performance degradation due to JVM default not being respected for socket linger option
Product: Tomcat 7 Reporter: David <david.lander>
Component: ConnectorsAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: critical    
Priority: P2    
Version: 7.0.53   
Target Milestone: ---   
Hardware: PC   
OS: All   

Description David 2014-04-16 16:11:20 UTC
According to http connector documentation, JVM defaults will be respected for socket linger options.  
https://tomcat.apache.org/tomcat-7.0-doc/config/http.html

Seems that linger is being set to false regardless of JVM default.

Setting priority to CRITICAL because on certain Solaris versions, calls to set linger cause performance problems and SocketExceptions.  I am experiencing this on my application.  See JVM bug.  http://bugs.java.com/view_bug.do?bug_id=6799574

Reproducable steps:
1)  Within server.xml, configure NIO http connector without an explicit linger setting:
    <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
               connectionTimeout="20000"
               redirectPort="8443" />


2)  Start Tomcat.  

Result: Linger is set to false for http nio connectors regardless of JVM default. 

Expected:  Linger parameter is not set on sockets.  JVM defaults are used.
Within setProperties method of SocketProperties.java,
breakpoint on line 194 should not be hit for http nio connector
socket.setSoLinger(soLingerOn.booleanValue(), soLingerTime.intValue()); 



Problem is that in the Http11NioProtocol constructor, a hard coded default value is set: 

    public Http11NioProtocol() {
        .... 
        setSoLinger(Constants.DEFAULT_CONNECTION_LINGER);  // -1
        ....  
    }

Any Java program can change the default socket factory for that JVM.  Tomcat cannot assume any particular default value for linger.  As per Tomcat's documentation, Tomcat should not be setting linger on the underlying socket unless it is specified within server.xml.

I suspect that this applies to other connectors as well e.g. AJP.
Comment 1 Mark Thomas 2014-04-24 11:38:27 UTC
Fixed in 8.0.x for 8.0.6 onwards and in 7.0.x for 7.0.54 onwards.
Comment 2 Mark Thomas 2014-04-24 13:33:08 UTC
Removing the default broke lots of stuff.

Further explicitly disabling socket linger is a sensible default for a web server.

The docs will be updated to reflect the actual default.

A possible work around for Solaris is to specify values for socket linger that Solaris finds acceptable.
Comment 3 Mark Thomas 2014-04-24 13:38:24 UTC
Docs updated for 8.0.x for 8.0.6 and 7.0.x for 7.0.54.
Comment 4 David 2014-04-24 13:52:12 UTC
Mark,

On my end we have the following scenario:
1)  Start Tomcat
2)  Tomcat binds to port and starts loading webapps
3)  My web app has a servlet for which load-on-startup is set to True.  Tomcat starts to load the servlet.
4)  While Tomcat is loading the servlet, client establishes a TCP connection and sends a TCP request.
5)  Tomcat is still loading the load-on-startup servlet, so the TCP request sits in the OS buffer.
6)  Client gets fed up and closes the TCP connection.
7)  Tomcat finishes loading the load-on-startup servlet.  
8)  Tomcat Acceptor thread starts accepting TCP requests that have built up in the OS buffer
9) Tomcat tries to set various properties on the socket.

The problem is that the CLIENT HAS ALREADY CLOSED THE CONNECTION (SEE STEP 7)

Result:  SocketExceptions in Tomcat log file.

Should the above be logged in a separate bug or do you have any other insight.  

Thanks,
David
Comment 5 Mark Thomas 2014-04-24 13:55:06 UTC
(In reply to David from comment #4)
> On my end we have the following scenario:

<snip/>

Bugzilla is not a support forum. This question belongs on the Tomcat users mailing list.
Comment 6 Konstantin Kolinko 2014-04-24 15:43:57 UTC
(In reply to David from comment #4)

First, that would better be tracked as a separate issue.

Second, it cannot be said much without knowing your Tomcat version and stacktrace of the error.

JioEndpoint and AprEndpoint implementations of setSocketOptions() log socket exceptions at debug level (the latter logs all errors at debug level).

NioEndpoint, Nio2Endpoint implementations of setSocketOptions() may need a fix.