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

This commit is contained in:
Allan Yang 2018-10-18 14:40:38 -07:00 committed by Michael Stack
parent bc7628a8c3
commit 05d22ed960
No known key found for this signature in database
GPG Key ID: 9816C7FC8ACC93D2
1 changed files with 17 additions and 0 deletions

View File

@ -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 {