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

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


The following commit(s) were added to refs/heads/10.1.x by this push:
     new 1d6d6325e2 Handle concurrent completion and timeout
1d6d6325e2 is described below

commit 1d6d6325e2b4f7a749ffc0d1508d457299aa376c
Author: Mark Thomas <[email protected]>
AuthorDate: Sat Nov 7 20:58:31 2026 +0000

    Handle concurrent completion and timeout
    
    Co-authored by: Claude / Sonnet 5.5
---
 .../apache/tomcat/util/net/SocketWrapperBase.java  | 36 +++++++++++++++++++---
 1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/java/org/apache/tomcat/util/net/SocketWrapperBase.java 
b/java/org/apache/tomcat/util/net/SocketWrapperBase.java
index a8f64ad832..909aaa1fa8 100644
--- a/java/org/apache/tomcat/util/net/SocketWrapperBase.java
+++ b/java/org/apache/tomcat/util/net/SocketWrapperBase.java
@@ -1699,14 +1699,22 @@ public abstract class SocketWrapperBase<E> {
                             timeoutMillis = (timeoutExpiry - 
System.nanoTime()) / 1_000_000;
                         }
                         if (state.state == CompletionState.PENDING) {
-                            if (handler != null && 
state.callHandler.compareAndSet(true, false)) {
-                                handler.failed(new 
SocketTimeoutException(getTimeoutMsg(read)), attachment);
+                            if (handler != null) {
+                                if (state.callHandler.compareAndSet(true, 
false)) {
+                                    handler.failed(new 
SocketTimeoutException(getTimeoutMsg(read)), attachment);
+                                } else {
+                                    awaitHandlerCompletion(state);
+                                }
                             }
                             return CompletionState.ERROR;
                         }
                     } catch (InterruptedException e) {
-                        if (handler != null && 
state.callHandler.compareAndSet(true, false)) {
-                            handler.failed(new 
SocketTimeoutException(getTimeoutMsg(read)), attachment);
+                        if (handler != null) {
+                            if (state.callHandler.compareAndSet(true, false)) {
+                                handler.failed(new 
SocketTimeoutException(getTimeoutMsg(read)), attachment);
+                            } else {
+                                awaitHandlerCompletion(state);
+                            }
                         }
                         return CompletionState.ERROR;
                     }
@@ -1717,6 +1725,26 @@ public abstract class SocketWrapperBase<E> {
     }
 
 
+    /**
+     * The completion thread has claimed the right to call the handler but has 
not yet finished doing so. Wait for it to
+     * finish (it updates the state and notifies once the handler has 
returned) so that the caller does not return
+     * before the handler has been called. The caller must hold the monitor 
for the state.
+     */
+    private void awaitHandlerCompletion(OperationState<?> state) {
+        boolean interrupted = false;
+        while (state.state == CompletionState.PENDING) {
+            try {
+                state.wait();
+            } catch (InterruptedException e) {
+                interrupted = true;
+            }
+        }
+        if (interrupted) {
+            Thread.currentThread().interrupt();
+        }
+    }
+
+
     private String getTimeoutMsg(boolean read) {
         if (read) {
             return sm.getString("socketWrapper.readTimeout");


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to