Repository: hbase
Updated Branches:
  refs/heads/branch-2.1 915e87ecf -> 1afedc608


HBASE-21292 IdLock.getLockEntry() may hang if interrupted


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/1afedc60
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/1afedc60
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/1afedc60

Branch: refs/heads/branch-2.1
Commit: 1afedc608e3b299f705c73331e279a8a7065d31e
Parents: 915e87e
Author: Allan Yang <[email protected]>
Authored: Thu Oct 18 14:40:38 2018 -0700
Committer: Michael Stack <[email protected]>
Committed: Thu Oct 18 14:41:16 2018 -0700

----------------------------------------------------------------------
 .../java/org/apache/hadoop/hbase/util/IdLock.java  | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/1afedc60/hbase-common/src/main/java/org/apache/hadoop/hbase/util/IdLock.java
----------------------------------------------------------------------
diff --git 
a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/IdLock.java 
b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/IdLock.java
index 414cc66..c4adfbf 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/IdLock.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/IdLock.java
@@ -81,6 +81,17 @@ public class IdLock {
               existing.wait();
             } catch (InterruptedException e) {
               --existing.numWaiters;  // Remove ourselves from waiters.
+              // HBASE-21292
+              // There is a rare case that interrupting and the lock owner 
thread call
+              // releaseLockEntry at the same time. Since the owner thread 
found there
+              // still one waiting, it won't remove the entry from the map. If 
the interrupted
+              // thread is the last one waiting on the lock, and since an 
exception is thrown,
+              // the 'existing' entry will stay in the map forever. Later 
threads which try to
+              // get this lock will stuck in a infinite loop because
+              // existing = map.putIfAbsent(entry.id, entry)) != null and 
existing.locked=false.
+              if (!existing.locked && existing.numWaiters == 0) {
+                map.remove(existing.id);
+              }
               throw new InterruptedIOException(
                   "Interrupted waiting to acquire sparse lock");
             }
@@ -135,6 +146,12 @@ public class IdLock {
 
             }
           } catch (InterruptedException e) {
+            // HBASE-21292
+            // Please refer to the comments in getLockEntry()
+            // the difference here is that we decrease numWaiters in finally 
block
+            if (!existing.locked && existing.numWaiters == 1) {
+              map.remove(existing.id);
+            }
             throw new InterruptedIOException(
                 "Interrupted waiting to acquire sparse lock");
           } finally {

Reply via email to