This is an automated email from the ASF dual-hosted git repository. mgrigorov pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/master by this push: new 14e5b8c Wrap 'error' and 'applicationIOE' with AtomicReference 14e5b8c is described below commit 14e5b8c2b1d0a88e6220a08feefba559bec2335e Author: Martin Tzvetanov Grigorov <mgrigo...@apache.org> AuthorDate: Thu Oct 1 13:29:42 2020 +0300 Wrap 'error' and 'applicationIOE' with AtomicReference Under high load it is possible that one thread makes the check for non-null and before the copy another thread to null-fy the member field. SEVERE: Servlet.service() for servlet [plaintext] in context with path [] threw exception java.lang.NullPointerException: Cannot throw exception because "ioe" is null at org.apache.coyote.http2.Http2UpgradeHandler.handleAppInitiatedIOException(Http2UpgradeHandler.java:797) at org.apache.coyote.http2.Http2AsyncUpgradeHandler.handleAsyncException(Http2AsyncUpgradeHandler.java:276) at org.apache.coyote.http2.Http2AsyncUpgradeHandler.writeWindowUpdate(Http2AsyncUpgradeHandler.java:252) at org.apache.coyote.http2.Stream$StreamInputBuffer.doRead(Stream.java:1088) at org.apache.coyote.Request.doRead(Request.java:555) at org.apache.catalina.connector.InputBuffer.realReadBytes(InputBuffer.java:336) at org.apache.catalina.connector.InputBuffer.checkByteBufferEof(InputBuffer.java:632) at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:362) at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:132) at org.apache.catalina.connector.Request.readPostBody(Request.java:3308) at org.apache.catalina.connector.Request.parseParameters(Request.java:3241) at org.apache.catalina.connector.Request.getParameter(Request.java:1124) at org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:381) at info.mgsolutions.tomcat.PlainTextServlet.doPost(PlainTextServlet.java:41) at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ... --- .../coyote/http2/Http2AsyncUpgradeHandler.java | 36 ++++++++++++---------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java b/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java index 9c274ac..defbb1c 100644 --- a/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java @@ -25,6 +25,7 @@ import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import jakarta.servlet.http.WebConnection; @@ -43,8 +44,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { // Because of the compression used, headers need to be written to the // network in the same order they are generated. private final Object headerWriteLock = new Object(); - private Throwable error = null; - private IOException applicationIOE = null; + private final AtomicReference<Throwable> error = new AtomicReference<>(); + private final AtomicReference<IOException> applicationIOE = new AtomicReference<>(); public Http2AsyncUpgradeHandler(Http2Protocol protocol, Adapter adapter, Request coyoteRequest) { @@ -57,7 +58,7 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { } @Override public void failed(Throwable t, Void attachment) { - error = t; + error.set(t); } }; private final CompletionHandler<Long, Void> applicationErrorCompletion = new CompletionHandler<Long, Void>() { @@ -67,9 +68,9 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { @Override public void failed(Throwable t, Void attachment) { if (t instanceof IOException) { - applicationIOE = (IOException) t; + applicationIOE.set((IOException) t); } - error = t; + error.set(t); } }; @@ -109,12 +110,13 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE, errorCompletion, ByteBuffer.wrap(localSettings.getSettingsFrameForPending()), ByteBuffer.wrap(createWindowUpdateForSettings())); - if (error != null) { + Throwable err = error.get(); + if (err != null) { String msg = sm.getString("upgradeHandler.sendPrefaceFail", connectionId); if (log.isDebugEnabled()) { log.debug(msg); } - throw new ProtocolException(msg, error); + throw new ProtocolException(msg, err); } } @@ -270,17 +272,17 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { private void handleAsyncException() throws IOException { - if (applicationIOE != null) { - IOException ioe = applicationIOE; - applicationIOE = null; + IOException ioe = applicationIOE.getAndSet(null); + if (ioe != null) { handleAppInitiatedIOException(ioe); - } else if (error != null) { - Throwable error = this.error; - this.error = null; - if (error instanceof IOException) { - throw (IOException) error; - } else { - throw new IOException(error); + } else { + Throwable err = this.error.getAndSet(null); + if (err != null) { + if (err instanceof IOException) { + throw (IOException) err; + } else { + throw new IOException(err); + } } } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org