Bug 58817

Summary: ArrayIndexOutOfBoundsException at shutdown if running with mapperContextRootRedirectEnabled="false"
Product: Tomcat 6 Reporter: Konstantin Kolinko <knst.kolinko>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Severity: normal    
Priority: P2    
Version: unspecified   
Target Milestone: default   
Hardware: PC   
OS: All   
Attachments: catalina.2016-01-07.log

Description Konstantin Kolinko 2016-01-07 01:53:47 UTC
Created attachment 33415 [details]

Noted when running a week old build of Tomcat 6 that used a different default value for mapperContextRootRedirectEnabled.

Steps to reproduce with current Tomcat 6 trunk:
1. Edit default conf/context.xml as
<Context mapperContextRootRedirectEnabled="false">

2. Run
catalina.bat start
catalina.bat stop

3. Tomcat shuts down successfully (immediately), but catalina.2016-01-07.log contains 2 copies of the following message:

07.01.2016 4:50:30 org.apache.catalina.connector.MapperListener handleNotification
WARNING: Error unregistering webapp Catalina:j2eeType=WebModule,name=//localhost/,J2EEApplication=none,J2EEServer=none
java.lang.ArrayIndexOutOfBoundsException: -1
	at org.apache.tomcat.util.http.mapper.Mapper.internalMapWrapper(Mapper.java:769)
	at org.apache.tomcat.util.http.mapper.Mapper.internalMap(Mapper.java:691)
	at org.apache.tomcat.util.http.mapper.Mapper.map(Mapper.java:577)
	at org.apache.catalina.connector.MapperListener.unregisterContext(MapperListener.java:481)

See attached log file for details.
Comment 1 Konstantin Kolinko 2016-01-07 01:58:32 UTC
Only Tomcat 6 is affected.
I tested current 7/8/9 trunks and they shut down cleanly in this configuration.
Comment 2 Konstantin Kolinko 2016-01-31 17:45:48 UTC
1. Comparing Mapper.internalMapWrapper() implementations between Tomcat 6 and Tomcat 7, they are not very different.

The only substantial difference is a missing block of code in Tomcat 6 (-- the code block just above "Rule 7". In Tomcat 7 it is commented as "/* welcome file processing - take 2"),  but it does not matter for this bug. It fails earlier.

2. MapperListener implementations are quite different. In Tomcat 7 it is a LifecycleListener, and has a reference to Context that is the cause of the event.

In Tomcat 6 it is a NotificationListener and this feature is triggered by unregistration of a JMX MBean. - See stacktrace attached in Description (Comment 0) of this bug.

As NotificationListener in Tomcat 6 does not have a reference to Context, it uses Mapper to get one, simulating a request with (host name = hostName, uri = contextName).

For ROOT context the uri becomes "", and the failure happens.

3. A similar call to Mapper.map() is used in Tomcat 7 and later to implement ApplicationContext.getContext(uri). There is a check in that method that uri.startsWith("/"), so it does not use an empty URI.

- NotificationListener of Tomcat 6 is the only place in Tomcat 6/7/8/9 that calls Mapper.map() with an empty string as URI. While it is possible to improve Mapper, I think it is sufficient to add workaround to NotificationListener to use a valid URI ("/") in this case.
Comment 3 Konstantin Kolinko 2016-01-31 18:04:05 UTC
Fixed in Tomcat 6 by r1727846 and will be in 6.0.45 onwards.