mirror of https://github.com/grpc/grpc-java.git
xds: Fix WeakReference bug in SharedCallCounterMap (#8466)
Fixes #8397. #8397 is caused by mistakenly clearing up a map entry right after the entry is recreated after gc. Reproduced in regression test.
This commit is contained in:
parent
2faa748797
commit
07747c59a2
|
|
@ -58,8 +58,14 @@ final class SharedCallCounterMap implements CallCounterProvider {
|
||||||
counters.put(cluster, clusterCounters);
|
counters.put(cluster, clusterCounters);
|
||||||
}
|
}
|
||||||
CounterReference ref = clusterCounters.get(edsServiceName);
|
CounterReference ref = clusterCounters.get(edsServiceName);
|
||||||
AtomicLong counter;
|
AtomicLong counter = null;
|
||||||
if (ref == null || (counter = ref.get()) == null) {
|
if (ref != null) {
|
||||||
|
counter = ref.get();
|
||||||
|
if (counter == null) {
|
||||||
|
ref.enqueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (counter == null) {
|
||||||
counter = new AtomicLong();
|
counter = new AtomicLong();
|
||||||
ref = new CounterReference(counter, refQueue, cluster, edsServiceName);
|
ref = new CounterReference(counter, refQueue, cluster, edsServiceName);
|
||||||
clusterCounters.put(edsServiceName, ref);
|
clusterCounters.put(edsServiceName, ref);
|
||||||
|
|
@ -73,6 +79,9 @@ final class SharedCallCounterMap implements CallCounterProvider {
|
||||||
CounterReference ref;
|
CounterReference ref;
|
||||||
while ((ref = (CounterReference) refQueue.poll()) != null) {
|
while ((ref = (CounterReference) refQueue.poll()) != null) {
|
||||||
Map<String, CounterReference> clusterCounter = counters.get(ref.cluster);
|
Map<String, CounterReference> clusterCounter = counters.get(ref.cluster);
|
||||||
|
if (clusterCounter.get(ref.edsServiceName) != ref) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
clusterCounter.remove(ref.edsServiceName);
|
clusterCounter.remove(ref.edsServiceName);
|
||||||
if (clusterCounter.isEmpty()) {
|
if (clusterCounter.isEmpty()) {
|
||||||
counters.remove(ref.cluster);
|
counters.remove(ref.cluster);
|
||||||
|
|
|
||||||
|
|
@ -62,4 +62,22 @@ public class SharedCallCounterMapTest {
|
||||||
map.cleanQueue();
|
map.cleanQueue();
|
||||||
assertThat(counters).isEmpty();
|
assertThat(counters).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void gcAndRecreate() {
|
||||||
|
@SuppressWarnings("UnusedVariable") // assign to null for GC only
|
||||||
|
AtomicLong counter = map.getOrCreate(CLUSTER, EDS_SERVICE_NAME);
|
||||||
|
final CounterReference ref = counters.get(CLUSTER).get(EDS_SERVICE_NAME);
|
||||||
|
assertThat(counter.get()).isEqualTo(0);
|
||||||
|
counter = null;
|
||||||
|
GcFinalization.awaitDone(new FinalizationPredicate() {
|
||||||
|
@Override
|
||||||
|
public boolean isDone() {
|
||||||
|
return ref.isEnqueued();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
map.getOrCreate(CLUSTER, EDS_SERVICE_NAME);
|
||||||
|
assertThat(counters.get(CLUSTER)).isNotNull();
|
||||||
|
assertThat(counters.get(CLUSTER).get(EDS_SERVICE_NAME)).isNotNull();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue