This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/9.0.x by this push:
     new 25a1da7  Expand on fix for BZ 65757 - check for specific request thread
25a1da7 is described below

commit 25a1da7753cd8c438958ca27475fec62050bce3f
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Mon Jan 10 13:40:58 2022 +0000

    Expand on fix for BZ 65757 - check for specific request thread
    
    Previous check was for any container thread. New check looks for the
    specific container thread currently assigned to the request/response.
---
 java/org/apache/coyote/AbstractProtocol.java       |  4 ----
 java/org/apache/coyote/AsyncStateMachine.java      | 10 +++++++---
 java/org/apache/coyote/ContainerThreadMarker.java  |  3 +++
 .../http11/upgrade/UpgradeServletInputStream.java  |  5 +++--
 .../http11/upgrade/UpgradeServletOutputStream.java |  5 +++--
 java/org/apache/coyote/http2/StreamProcessor.java  |  3 ---
 .../tomcat/util/net/ContainerThreadMarker.java     |  3 +++
 .../catalina/nonblocking/TestNonBlockingAPI.java   | 23 ++++++++++++++++++++--
 webapps/docs/changelog.xml                         |  6 ++++++
 9 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/java/org/apache/coyote/AbstractProtocol.java 
b/java/org/apache/coyote/AbstractProtocol.java
index c7042e1..949dbc5 100644
--- a/java/org/apache/coyote/AbstractProtocol.java
+++ b/java/org/apache/coyote/AbstractProtocol.java
@@ -828,8 +828,6 @@ public abstract class AbstractProtocol<S> implements 
ProtocolHandler,
                 return SocketState.CLOSED;
             }
 
-            ContainerThreadMarker.set();
-
             try {
                 if (processor == null) {
                     String negotiatedProtocol = 
wrapper.getNegotiatedProtocol();
@@ -1049,8 +1047,6 @@ public abstract class AbstractProtocol<S> implements 
ProtocolHandler,
                 // with "ERROR" level, so it will show up even on
                 // less-than-verbose logs.
                 
getLog().error(sm.getString("abstractConnectionHandler.error"), e);
-            } finally {
-                ContainerThreadMarker.clear();
             }
 
             // Make sure socket/processor is removed from the list of current
diff --git a/java/org/apache/coyote/AsyncStateMachine.java 
b/java/org/apache/coyote/AsyncStateMachine.java
index 3176246..472a48b 100644
--- a/java/org/apache/coyote/AsyncStateMachine.java
+++ b/java/org/apache/coyote/AsyncStateMachine.java
@@ -305,7 +305,8 @@ class AsyncStateMachine {
 
 
     synchronized boolean asyncComplete() {
-        if (!ContainerThreadMarker.isContainerThread() &&
+        Request request = processor.getRequest();
+        if ((request == null || !request.isRequestThread()) &&
                 (state == AsyncState.STARTING || state == 
AsyncState.READ_WRITE_OP)) {
             updateState(AsyncState.COMPLETE_PENDING);
             return false;
@@ -367,7 +368,8 @@ class AsyncStateMachine {
 
 
     synchronized boolean asyncDispatch() {
-        if (!ContainerThreadMarker.isContainerThread() &&
+        Request request = processor.getRequest();
+        if ((request == null || !request.isRequestThread()) &&
                 (state == AsyncState.STARTING || state == 
AsyncState.READ_WRITE_OP)) {
             updateState(AsyncState.DISPATCH_PENDING);
             return false;
@@ -436,7 +438,9 @@ class AsyncStateMachine {
         } else {
             updateState(AsyncState.ERROR);
         }
-        return !ContainerThreadMarker.isContainerThread();
+
+        Request request = processor.getRequest();
+        return request == null || !request.isRequestThread();
     }
 
 
diff --git a/java/org/apache/coyote/ContainerThreadMarker.java 
b/java/org/apache/coyote/ContainerThreadMarker.java
index 0ba2ef0..2d651b3 100644
--- a/java/org/apache/coyote/ContainerThreadMarker.java
+++ b/java/org/apache/coyote/ContainerThreadMarker.java
@@ -21,7 +21,10 @@ package org.apache.coyote;
  * data from an incoming connection. Application created threads are not
  * container threads and neither are threads taken from the container thread
  * pool to execute AsyncContext.start(Runnable).
+ *
+ * @deprecated Unused. Will be removed in Tomcat 10.1.x
  */
+@Deprecated
 public class ContainerThreadMarker {
 
     public static boolean isContainerThread() {
diff --git 
a/java/org/apache/coyote/http11/upgrade/UpgradeServletInputStream.java 
b/java/org/apache/coyote/http11/upgrade/UpgradeServletInputStream.java
index 387581a..e5d4264 100644
--- a/java/org/apache/coyote/http11/upgrade/UpgradeServletInputStream.java
+++ b/java/org/apache/coyote/http11/upgrade/UpgradeServletInputStream.java
@@ -21,7 +21,7 @@ import java.io.IOException;
 import javax.servlet.ReadListener;
 import javax.servlet.ServletInputStream;
 
-import org.apache.coyote.ContainerThreadMarker;
+import org.apache.coyote.Request;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.ExceptionUtils;
@@ -106,7 +106,8 @@ public class UpgradeServletInputStream extends 
ServletInputStream {
         this.listener = listener;
 
         // Container is responsible for first call to onDataAvailable().
-        if (ContainerThreadMarker.isContainerThread()) {
+        Request request = processor.getRequest();
+        if (request != null && request.isRequestThread()) {
             processor.addDispatch(DispatchType.NON_BLOCKING_READ);
         } else {
             socketWrapper.registerReadInterest();
diff --git 
a/java/org/apache/coyote/http11/upgrade/UpgradeServletOutputStream.java 
b/java/org/apache/coyote/http11/upgrade/UpgradeServletOutputStream.java
index 84d8fa5..571fe9c 100644
--- a/java/org/apache/coyote/http11/upgrade/UpgradeServletOutputStream.java
+++ b/java/org/apache/coyote/http11/upgrade/UpgradeServletOutputStream.java
@@ -21,7 +21,7 @@ import java.io.IOException;
 import javax.servlet.ServletOutputStream;
 import javax.servlet.WriteListener;
 
-import org.apache.coyote.ContainerThreadMarker;
+import org.apache.coyote.Request;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.ExceptionUtils;
@@ -119,7 +119,8 @@ public class UpgradeServletOutputStream extends 
ServletOutputStream {
         synchronized (registeredLock) {
             registered = true;
             // Container is responsible for first call to onDataAvailable().
-            if (ContainerThreadMarker.isContainerThread()) {
+            Request request = processor.getRequest();
+            if (request != null && request.isRequestThread()) {
                 processor.addDispatch(DispatchType.NON_BLOCKING_WRITE);
             } else {
                 socketWrapper.registerWriteInterest();
diff --git a/java/org/apache/coyote/http2/StreamProcessor.java 
b/java/org/apache/coyote/http2/StreamProcessor.java
index 9b4b62f..3f26a8a 100644
--- a/java/org/apache/coyote/http2/StreamProcessor.java
+++ b/java/org/apache/coyote/http2/StreamProcessor.java
@@ -26,7 +26,6 @@ import javax.servlet.http.HttpServletResponse;
 import org.apache.coyote.AbstractProcessor;
 import org.apache.coyote.ActionCode;
 import org.apache.coyote.Adapter;
-import org.apache.coyote.ContainerThreadMarker;
 import org.apache.coyote.ContinueResponseTiming;
 import org.apache.coyote.ErrorState;
 import org.apache.coyote.Request;
@@ -73,7 +72,6 @@ class StreamProcessor extends AbstractProcessor {
             synchronized (this) {
                 // HTTP/2 equivalent of AbstractConnectionHandler#process() 
without the
                 // socket <-> processor mapping
-                ContainerThreadMarker.set();
                 SocketState state = SocketState.CLOSED;
                 try {
                     state = process(socketWrapper, event);
@@ -125,7 +123,6 @@ class StreamProcessor extends AbstractProcessor {
                     if (state == SocketState.CLOSED) {
                         recycle();
                     }
-                    ContainerThreadMarker.clear();
                 }
             }
         } finally {
diff --git a/java/org/apache/tomcat/util/net/ContainerThreadMarker.java 
b/java/org/apache/tomcat/util/net/ContainerThreadMarker.java
index 2ab6f68..7149945 100644
--- a/java/org/apache/tomcat/util/net/ContainerThreadMarker.java
+++ b/java/org/apache/tomcat/util/net/ContainerThreadMarker.java
@@ -21,7 +21,10 @@ package org.apache.tomcat.util.net;
  * data from an incoming connection. Application created threads are not
  * container threads and neither are threads taken from the container thread
  * pool to execute AsyncContext.start(Runnable).
+ *
+ * @deprecated Unused. Will be removed in Tomcat 10.1.x
  */
+@Deprecated
 public class ContainerThreadMarker {
 
     private static final ThreadLocal<Boolean> marker = new ThreadLocal<>();
diff --git a/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java 
b/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java
index dc1f580..99fedcd 100644
--- a/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java
+++ b/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java
@@ -20,6 +20,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Serializable;
+import java.lang.reflect.Field;
 import java.net.HttpURLConnection;
 import java.net.Socket;
 import java.net.URL;
@@ -55,16 +56,17 @@ import org.junit.Test;
 
 import org.apache.catalina.Context;
 import org.apache.catalina.Wrapper;
+import org.apache.catalina.core.AsyncContextImpl;
 import org.apache.catalina.startup.BytesStreamer;
 import org.apache.catalina.startup.SimpleHttpClient;
 import org.apache.catalina.startup.TesterServlet;
 import org.apache.catalina.startup.Tomcat;
 import org.apache.catalina.startup.TomcatBaseTest;
 import org.apache.catalina.valves.TesterAccessLogValve;
+import org.apache.coyote.Request;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.net.ContainerThreadMarker;
 
 public class TestNonBlockingAPI extends TomcatBaseTest {
 
@@ -75,6 +77,7 @@ public class TestNonBlockingAPI extends TomcatBaseTest {
     private static final byte[] DATA = new byte[WRITE_SIZE];
     private static final int WRITE_PAUSE_MS = 500;
 
+    private static final Field CTX_REQUEST_FIELD;
 
     static {
         // Use this sequence for padding to make it easier to spot errors
@@ -91,6 +94,15 @@ public class TestNonBlockingAPI extends TomcatBaseTest {
             System.arraycopy(
                     hex.getBytes(), 0, DATA, i * blockSize + padSize, hexSize);
         }
+
+        Field f = null;
+        try {
+            f = AsyncContextImpl.class.getDeclaredField("request");
+            f.setAccessible(true);
+        } catch (NoSuchFieldException | SecurityException e) {
+            Assert.fail();
+        }
+        CTX_REQUEST_FIELD = f;
     }
 
 
@@ -720,7 +732,14 @@ public class TestNonBlockingAPI extends TomcatBaseTest {
 
         @Override
         public void onDataAvailable() throws IOException {
-            if (ContainerThreadMarker.isContainerThread()) {
+            Request coyoteRequest;
+            try {
+                coyoteRequest = ((org.apache.catalina.connector.Request) 
CTX_REQUEST_FIELD.get(ctx)).getCoyoteRequest();
+            } catch (IllegalArgumentException | IllegalAccessException e) {
+                throw new IllegalStateException(e);
+            }
+
+            if (coyoteRequest.isRequestThread()) {
                 containerThreadCount.incrementAndGet();
             } else {
                 nonContainerThreadCount.incrementAndGet();
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 3f38547..004aea3 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -137,6 +137,12 @@
        container dispatch to another container thread. (remm)
       </fix>
       <fix>
+        Expand the fix for <bug>65757</bug> so that rather than just checking 
if
+        processing is happening on a container thread, the check is now if
+        processing is happening on the container thread currently allocated to
+        this request/response. (markt)
+      </fix>
+      <fix>
         Improve the fix for RST frame ordering added in 9.0.56 to avoid a
         potential deadlock on some systems in non-default configurations.
         (markt)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to