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 2017/05/10 07:33:52 UTC

[05/13] httpcomponents-core git commit: HTTPCORE-446: fixed deadlock in AbstractConnPool shutdown code

HTTPCORE-446: fixed deadlock in AbstractConnPool shutdown code


Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/commit/67bcb420
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/tree/67bcb420
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/diff/67bcb420

Branch: refs/heads/HTTPCORE-446
Commit: 67bcb4201e4cb2584d298c3c0a0e800c0825f7f3
Parents: 55d881e
Author: Oleg Kalnichevski <ol...@apache.org>
Authored: Wed Feb 15 15:10:22 2017 +0100
Committer: Oleg Kalnichevski <ol...@apache.org>
Committed: Wed Feb 15 15:10:22 2017 +0100

----------------------------------------------------------------------
 .../org/apache/http/pool/AbstractConnPool.java  | 47 +++++++++++---------
 1 file changed, 25 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/67bcb420/httpcore/src/main/java/org/apache/http/pool/AbstractConnPool.java
----------------------------------------------------------------------
diff --git a/httpcore/src/main/java/org/apache/http/pool/AbstractConnPool.java b/httpcore/src/main/java/org/apache/http/pool/AbstractConnPool.java
index d34cf24..25a6bfc 100644
--- a/httpcore/src/main/java/org/apache/http/pool/AbstractConnPool.java
+++ b/httpcore/src/main/java/org/apache/http/pool/AbstractConnPool.java
@@ -38,6 +38,8 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
@@ -190,37 +192,37 @@ public abstract class AbstractConnPool<T, C, E extends PoolEntry<T, C>>
 
         return new Future<E>() {
 
-            private volatile boolean cancelled;
-            private volatile boolean done;
-            private volatile E entry;
+            private final AtomicBoolean cancelled = new AtomicBoolean(false);
+            private final AtomicBoolean done = new AtomicBoolean(false);
+            private final AtomicReference<E> entryRef = new AtomicReference<E>(null);
 
             @Override
             public boolean cancel(final boolean mayInterruptIfRunning) {
-                cancelled = true;
-                lock.lock();
-                try {
-                    condition.signalAll();
-                } finally {
-                    lock.unlock();
-                }
-                synchronized (this) {
-                    final boolean result = !done;
-                    done = true;
+                if (cancelled.compareAndSet(false, true)) {
+                    done.set(true);
+                    lock.lock();
+                    try {
+                        condition.signalAll();
+                    } finally {
+                        lock.unlock();
+                    }
                     if (callback != null) {
                         callback.cancelled();
                     }
-                    return result;
+                    return true;
+                } else {
+                    return false;
                 }
             }
 
             @Override
             public boolean isCancelled() {
-                return cancelled;
+                return cancelled.get();
             }
 
             @Override
             public boolean isDone() {
-                return done;
+                return done.get();
             }
 
             @Override
@@ -234,6 +236,7 @@ public abstract class AbstractConnPool<T, C, E extends PoolEntry<T, C>>
 
             @Override
             public E get(final long timeout, final TimeUnit tunit) throws InterruptedException, ExecutionException, TimeoutException {
+                final E entry = entryRef.get();
                 if (entry != null) {
                     return entry;
                 }
@@ -250,16 +253,16 @@ public abstract class AbstractConnPool<T, C, E extends PoolEntry<T, C>>
                                     }
                                 }
                             }
-                            entry = leasedEntry;
-                            done = true;
-                            onLease(entry);
+                            entryRef.set(leasedEntry);
+                            done.set(true);
+                            onLease(leasedEntry);
                             if (callback != null) {
-                                callback.completed(entry);
+                                callback.completed(leasedEntry);
                             }
-                            return entry;
+                            return leasedEntry;
                         }
                     } catch (IOException ex) {
-                        done = true;
+                        done.set(true);
                         if (callback != null) {
                             callback.failed(ex);
                         }