Browse Source

Always use try/finally around DfsBlockCache.clockLock

Any RuntimeException or Error in this block will leave the lock
held by the caller thread, which can later result in deadlock or
just cache requests hanging forever because they cannot get to
the lock object.

Wrap everything in try/finally to prevent the lock from hanging,
even though a RuntimeException or Error should never happen in
any of these code paths.

Change-Id: Ibb3467f7ee4c06f617b737858b4be17b10d936e0
stable-1.2
Shawn O. Pearce 13 years ago
parent
commit
9652f16a47
  1. 76
      org.eclipse.jgit/src/org/eclipse/jgit/storage/dfs/DfsBlockCache.java

76
org.eclipse.jgit/src/org/eclipse/jgit/storage/dfs/DfsBlockCache.java

@ -389,36 +389,39 @@ public final class DfsBlockCache {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void reserveSpace(int reserve) { private void reserveSpace(int reserve) {
clockLock.lock(); clockLock.lock();
long live = liveBytes + reserve; try {
if (maxBytes < live) { long live = liveBytes + reserve;
Ref prev = clockHand; if (maxBytes < live) {
Ref hand = clockHand.next; Ref prev = clockHand;
do { Ref hand = clockHand.next;
if (hand.hot) { do {
// Value was recently touched. Clear if (hand.hot) {
// hot and give it another chance. // Value was recently touched. Clear
hand.hot = false; // hot and give it another chance.
prev = hand; hand.hot = false;
prev = hand;
hand = hand.next;
continue;
} else if (prev == hand)
break;
// No recent access since last scan, kill
// value and remove from clock.
Ref dead = hand;
hand = hand.next; hand = hand.next;
continue; prev.next = hand;
} else if (prev == hand) dead.next = null;
break; dead.value = null;
live -= dead.size;
// No recent access since last scan, kill dead.pack.cachedSize.addAndGet(-dead.size);
// value and remove from clock. statEvict++;
Ref dead = hand; } while (maxBytes < live);
hand = hand.next; clockHand = prev;
prev.next = hand; }
dead.next = null; liveBytes = live;
dead.value = null; } finally {
live -= dead.size; clockLock.unlock();
dead.pack.cachedSize.addAndGet(-dead.size);
statEvict++;
} while (maxBytes < live);
clockHand = prev;
} }
liveBytes = live;
clockLock.unlock();
} }
private void creditSpace(int credit) { private void creditSpace(int credit) {
@ -429,13 +432,16 @@ public final class DfsBlockCache {
private void addToClock(Ref ref, int credit) { private void addToClock(Ref ref, int credit) {
clockLock.lock(); clockLock.lock();
if (credit != 0) try {
liveBytes -= credit; if (credit != 0)
Ref ptr = clockHand; liveBytes -= credit;
ref.next = ptr.next; Ref ptr = clockHand;
ptr.next = ref; ref.next = ptr.next;
clockHand = ref; ptr.next = ref;
clockLock.unlock(); clockHand = ref;
} finally {
clockLock.unlock();
}
} }
void put(DfsBlock v) { void put(DfsBlock v) {

Loading…
Cancel
Save