The 'JspConfig.init()' method can be called simultaneously from multiple threads at the same time, but it is not synchronized, so the initialization code in the body can be executed simultaneously by multiple threads. This can lead to a 'jsp-property-group' configuration being added twice to the 'jspProperties' vector. The symptom we noticed was that on some runs, the contents of the 'include-prelude' and 'include-coda' elements would be included twice in all compiled jsp files. This bug is hard to reproduce because it requires a run where the first thing that happens is that multiple jsp files are requested simultaneously. However, after adding a field containing a synchronization object and synchronizing on it across the if (!initialized) { ... } block, we haven't seen the problem reoccur.
Created attachment 19615 [details] Patch that synchronizes initialization in 'JspConfig.init'
No, this additional sync will not be added. The recompilation checks should be sufficiently synchronized already.
For each page, compilation is synchronized, but it is not synchronized between pages. This is typically not a problem because most of the state for different pages isn't shared, but the 'JspConfig' instance is via the shared 'EmbeddedServletOptions' instance. Here is the top of the stack when 'JspConfig.init()' is first called: JspConfig.init() line: 202 JspConfig.findJspProperty(String) line: 254 AntCompiler(Compiler).generateJava() line: 112 AntCompiler(Compiler).compile(boolean, boolean) line: 295 AntCompiler(Compiler).compile(boolean) line: 276 AntCompiler(Compiler).compile() line: 264 JspCompilationContext.compile() line: 563 JspServletWrapper.service(HttpServletRequest, HttpServletResponse, boolean) line: 305 JspServlet.serviceJspFile(HttpServletRequest, HttpServletResponse, String, Throwable, boolean) line: 314 JspServlet.service(HttpServletRequest, HttpServletResponse) line: 264 JspServlet(HttpServlet).service(ServletRequest, ServletResponse) line: 861 The only synchronization that occurs in that stack is in 'JspServletWrapper.service', which synchronizes on 'this'. Each page has a separate 'JspServletWrapper' instance, but all instances share a common 'EmbeddedServletOptions', which contains the 'JspConfig'. Thus, the synchronization does not protect against multiple pages being compiled simultaneously and calling 'init()' on the same 'JspConfig' instance at the same time.
Thanks for the report and the analysis. This has been fixed in trunk and proposed for 5.5.x and 6.0.x.
This has been fixed for 5.5.x and will be included in 5.5.29 onwards.
This has been fixed in 6.0.x and will be included in 6.0.21 onwards.