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);
|
||||
}
|
||||
CounterReference ref = clusterCounters.get(edsServiceName);
|
||||
AtomicLong counter;
|
||||
if (ref == null || (counter = ref.get()) == null) {
|
||||
AtomicLong counter = null;
|
||||
if (ref != null) {
|
||||
counter = ref.get();
|
||||
if (counter == null) {
|
||||
ref.enqueue();
|
||||
}
|
||||
}
|
||||
if (counter == null) {
|
||||
counter = new AtomicLong();
|
||||
ref = new CounterReference(counter, refQueue, cluster, edsServiceName);
|
||||
clusterCounters.put(edsServiceName, ref);
|
||||
|
|
@ -73,6 +79,9 @@ final class SharedCallCounterMap implements CallCounterProvider {
|
|||
CounterReference ref;
|
||||
while ((ref = (CounterReference) refQueue.poll()) != null) {
|
||||
Map<String, CounterReference> clusterCounter = counters.get(ref.cluster);
|
||||
if (clusterCounter.get(ref.edsServiceName) != ref) {
|
||||
continue;
|
||||
}
|
||||
clusterCounter.remove(ref.edsServiceName);
|
||||
if (clusterCounter.isEmpty()) {
|
||||
counters.remove(ref.cluster);
|
||||
|
|
|
|||
|
|
@ -62,4 +62,22 @@ public class SharedCallCounterMapTest {
|
|||
map.cleanQueue();
|
||||
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