Author: markt
Date: Thu Aug 9 13:42:16 2018
New Revision: 1837726
URL: http://svn.apache.org/viewvc?rev=1837726&view=rev
Log:
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=62603
Fix a potential race condition when development mode is disabled and background
compilation checks are enabled. It was possible that some updates would not
take effect and/or ClassNotFoundExceptions would occur.
Modified:
tomcat/trunk/java/org/apache/jasper/compiler/JspRuntimeContext.java
tomcat/trunk/java/org/apache/jasper/servlet/JspServletWrapper.java
tomcat/trunk/webapps/docs/changelog.xml
Modified: tomcat/trunk/java/org/apache/jasper/compiler/JspRuntimeContext.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/JspRuntimeContext.java?rev=1837726&r1=1837725&r2=1837726&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/compiler/JspRuntimeContext.java
(original)
+++ tomcat/trunk/java/org/apache/jasper/compiler/JspRuntimeContext.java Thu Aug
9 13:42:16 2018
@@ -28,11 +28,14 @@ import java.security.CodeSource;
import java.security.PermissionCollection;
import java.security.Policy;
import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
import org.apache.jasper.Constants;
import org.apache.jasper.JspCompilationContext;
@@ -176,6 +179,11 @@ public final class JspRuntimeContext {
*/
private final Map<String,SmapStratum> smaps = new ConcurrentHashMap<>();
+ /**
+ * Flag that indicates if a background compilation check is in progress.
+ */
+ private volatile boolean compileCheckInProgress = false;
+
// ------------------------------------------------------ Public Methods
@@ -361,6 +369,11 @@ public final class JspRuntimeContext {
return;
}
+ List<JspServletWrapper> wrappersToReload = new ArrayList<>();
+ // Tell JspServletWrapper to ignore the reload attribute while this
+ // check is in progress. See BZ 62603.
+ compileCheckInProgress = true;
+
Object [] wrappers = jsps.values().toArray();
for (int i = 0; i < wrappers.length; i++ ) {
JspServletWrapper jsw = (JspServletWrapper)wrappers[i];
@@ -370,6 +383,9 @@ public final class JspRuntimeContext {
synchronized(jsw) {
try {
ctxt.compile();
+ if (jsw.getReload()) {
+ wrappersToReload.add(jsw);
+ }
} catch (FileNotFoundException ex) {
ctxt.incrementRemoved();
} catch (Throwable t) {
@@ -380,6 +396,31 @@ public final class JspRuntimeContext {
}
}
+ // See BZ 62603.
+ // OK to process reload flag now.
+ compileCheckInProgress = false;
+ // Ensure all servlets and tags that need to be reloaded, are reloaded.
+ for (JspServletWrapper jsw : wrappersToReload) {
+ // Triggers reload
+ try {
+ if (jsw.isTagFile()) {
+ // Although this is a public method, all other paths to
this
+ // method use this sync and it is required to prevent race
+ // conditions during the reload.
+ synchronized (this) {
+ jsw.loadTagFile();
+ }
+ } else {
+ jsw.getServlet();
+ }
+ } catch (ServletException e) {
+ jsw.getServletContext().log("Servlet reload failed", e);
+ }
+ }
+ }
+
+ public boolean isCompileCheckInProgress() {
+ return compileCheckInProgress;
}
/**
Modified: tomcat/trunk/java/org/apache/jasper/servlet/JspServletWrapper.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/servlet/JspServletWrapper.java?rev=1837726&r1=1837725&r2=1837726&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/servlet/JspServletWrapper.java
(original)
+++ tomcat/trunk/java/org/apache/jasper/servlet/JspServletWrapper.java Thu Aug
9 13:42:16 2018
@@ -153,15 +153,29 @@ public class JspServletWrapper {
this.reload = reload;
}
+ public boolean getReload() {
+ return reload;
+ }
+
+ private boolean getReloadInternal() {
+ return firstTime || reload &&
!ctxt.getRuntimeContext().isCompileCheckInProgress();
+ }
+
public Servlet getServlet() throws ServletException {
- // DCL on 'reload' requires that 'reload' be volatile
- // (this also forces a read memory barrier, ensuring the
- // new servlet object is read consistently)
- if (reload) {
+ /*
+ * DCL on 'reload' requires that 'reload' be volatile
+ * (this also forces a read memory barrier, ensuring the new servlet
+ * object is read consistently).
+ *
+ * When running in non development mode with a checkInterval it is
+ * possible (see BZ 62603) for a race condition to cause failures
+ * if a Servlet or tag is reloaded while a compile check is running
+ */
+ if (getReloadInternal()) {
synchronized (this) {
// Synchronizing on jsw enables simultaneous loading
// of different pages, but not the same page.
- if (reload) {
+ if (getReloadInternal()) {
// This is to maintain the original protocol.
destroy();
@@ -254,7 +268,7 @@ public class JspServletWrapper {
}
}
- if (reload) {
+ if (getReloadInternal()) {
tagHandlerClass = ctxt.load();
reload = false;
}
Modified: tomcat/trunk/webapps/docs/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1837726&r1=1837725&r2=1837726&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Thu Aug 9 13:42:16 2018
@@ -162,16 +162,22 @@
Correctly decode URL paths (<code>+</code> should not be decoded to a
space in the path) in the Jasper class loader. (markt)
</fix>
+ <fix>
+ <bug>62603</bug>: Fix a potential race condition when development mode
+ is disabled and background compilation checks are enabled. It was
+ possible that some updates would not take effect and/or
+ <code>ClassNotFoundException</code>s would occur. (markt)
+ </fix>
</changelog>
</subsection>
- <subseciton name="WebSocket">
+ <subsection name="WebSocket">
<changelog>
<fix>
<bug>62596</bug>: Remove the limit on the size of the initial HTTP
upgrade request used to establish the web socket connection. (markt)
</fix>
</changelog>
- </subseciton>
+ </subsection>
<subsection name="Web applications">
<changelog>
<add>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]