You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2019/08/09 13:02:18 UTC

[httpcomponents-core] branch HTTPCORE-588 created (now 1e9d57e)

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

olegk pushed a change to branch HTTPCORE-588
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git.


      at 1e9d57e  HTTPCORE-588: race condition in ComplexCancellable that can lead to operational dependency not being correctly cancelled

This branch includes the following new commits:

     new 1e9d57e  HTTPCORE-588: race condition in ComplexCancellable that can lead to operational dependency not being correctly cancelled

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[httpcomponents-core] 01/01: HTTPCORE-588: race condition in ComplexCancellable that can lead to operational dependency not being correctly cancelled

Posted by ol...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch HTTPCORE-588
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git

commit 1e9d57e176b142ed05f48928e36c04149c1f9385
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Fri Aug 9 12:22:24 2019 +0200

    HTTPCORE-588: race condition in ComplexCancellable that can lead to operational dependency not being correctly cancelled
---
 .../hc/core5/concurrent/ComplexCancellable.java    | 28 ++++++++++------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/httpcore5/src/main/java/org/apache/hc/core5/concurrent/ComplexCancellable.java b/httpcore5/src/main/java/org/apache/hc/core5/concurrent/ComplexCancellable.java
index d306d6a..1b43219 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/concurrent/ComplexCancellable.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/concurrent/ComplexCancellable.java
@@ -26,8 +26,7 @@
  */
 package org.apache.hc.core5.concurrent;
 
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.atomic.AtomicMarkableReference;
 
 import org.apache.hc.core5.util.Args;
 
@@ -40,37 +39,36 @@ import org.apache.hc.core5.util.Args;
  */
 public final class ComplexCancellable implements CancellableDependency {
 
-    private final AtomicReference<Cancellable> dependencyRef;
-    private final AtomicBoolean cancelled;
+    private final AtomicMarkableReference<Cancellable> dependencyRef;
 
     public ComplexCancellable() {
-        this.dependencyRef = new AtomicReference<>(null);
-        this.cancelled = new AtomicBoolean(false);
+        this.dependencyRef = new AtomicMarkableReference<>(null, false);
     }
 
     @Override
     public boolean isCancelled() {
-        return cancelled.get();
+        return dependencyRef.isMarked();
     }
 
     @Override
     public void setDependency(final Cancellable dependency) {
         Args.notNull(dependency, "dependency");
-        if (!cancelled.get()) {
-            dependencyRef.set(dependency);
-        } else {
+        final Cancellable actualDependency = dependencyRef.getReference();
+        if (!dependencyRef.compareAndSet(actualDependency, dependency, false, false)) {
             dependency.cancel();
         }
     }
 
     @Override
     public boolean cancel() {
-        if (cancelled.compareAndSet(false, true)) {
-            final Cancellable dependency = dependencyRef.getAndSet(null);
-            if (dependency != null) {
-                dependency.cancel();
+        while (!dependencyRef.isMarked()) {
+            final Cancellable actualDependency = dependencyRef.getReference();
+            if (dependencyRef.compareAndSet(actualDependency, actualDependency, false, true)) {
+                if (actualDependency != null) {
+                    actualDependency.cancel();
+                }
+                return true;
             }
-            return true;
         }
         return false;
     }