|
15 | 15 | */ |
16 | 16 | package io.micrometer.concurrencytests; |
17 | 17 |
|
| 18 | +import io.micrometer.core.Issue; |
18 | 19 | import io.micrometer.core.instrument.Counter; |
19 | 20 | import io.micrometer.core.instrument.MeterRegistry; |
20 | 21 | import io.micrometer.core.instrument.simple.SimpleMeterRegistry; |
21 | 22 | import org.openjdk.jcstress.annotations.*; |
22 | 23 | import org.openjdk.jcstress.infra.results.LL_Result; |
| 24 | +import org.openjdk.jcstress.infra.results.L_Result; |
23 | 25 | import org.openjdk.jcstress.infra.results.Z_Result; |
24 | 26 |
|
25 | 27 | public class MeterRegistryConcurrencyTest { |
@@ -145,4 +147,45 @@ public void arbiter(LL_Result r) { |
145 | 147 |
|
146 | 148 | } |
147 | 149 |
|
| 150 | + /* |
| 151 | + * Verify the fix for a ConcurrentModificationException that was being thrown in the |
| 152 | + * tested scenario. The late registration of a MeterFilter causes iteration of the |
| 153 | + * KeySet of the preFilterIdToMeterMap to add them to the stalePreFilterIds set. This |
| 154 | + * iteration could happen at the same time a new meter is being registered, thus added |
| 155 | + * to the preFilterIdToMeterMap, modifying it while iterating over its KeySet. |
| 156 | + */ |
| 157 | + @Issue("gh-5489") |
| 158 | + @JCStressTest |
| 159 | + @Outcome(id = "OK", expect = Expect.ACCEPTABLE, desc = "No exception") |
| 160 | + @Outcome(expect = Expect.FORBIDDEN, desc = "Exception thrown") |
| 161 | + @State |
| 162 | + public static class ConfigureLateMeterFilterWithNewMeterRegister { |
| 163 | + |
| 164 | + MeterRegistry registry = new SimpleMeterRegistry(); |
| 165 | + |
| 166 | + public ConfigureLateMeterFilterWithNewMeterRegister() { |
| 167 | + // registry not empty so the MeterFilter is treated as late configuration |
| 168 | + registry.counter("c1"); |
| 169 | + } |
| 170 | + |
| 171 | + @Actor |
| 172 | + public void actor1() { |
| 173 | + // adds a new meter to preMap, a concurrent modification if not guarded |
| 174 | + registry.counter("c2"); |
| 175 | + } |
| 176 | + |
| 177 | + @Actor |
| 178 | + public void actor2(L_Result r) { |
| 179 | + try { |
| 180 | + // iterates over preMap keys to add all to the staleIds |
| 181 | + registry.config().commonTags("common", "tag"); |
| 182 | + r.r1 = "OK"; |
| 183 | + } |
| 184 | + catch (Throwable e) { |
| 185 | + r.r1 = e.getClass().getSimpleName(); |
| 186 | + } |
| 187 | + } |
| 188 | + |
| 189 | + } |
| 190 | + |
148 | 191 | } |
0 commit comments