Context
Found during a cross-SDK audit related to dotnet-server-sdk #204, which fixed a flush-mutex-leak in the .NET SDK where EndFlush() wasn't called if the WASM bucketing engine threw. That audit flagged a related (but distinct) issue here.
Problem
In EventQueueManager.java, flushEvents() sets isFlushingEvents = true before the publish loop and isFlushingEvents = false after — but not in a finally block:
// line 88
isFlushingEvents = true;
for (FlushPayload payload : flushPayloads) {
eventCount += payload.eventCount;
publishEvents(this.sdkKey, payload); // throws InterruptedException
}
isFlushingEvents = false; // line 93 — never reached if loop throws
publishEvents() declares throws InterruptedException. If that exception escapes, isFlushingEvents stays true for the lifetime of the process. Every subsequent call to flushEvents() returns early at line 70:
if (isFlushingEvents) return;
Events accumulate and are never sent.
Severity: Low. getResponse() catches IOException and returns 500, and the synchronized on flushEvents() means the JVM mutex releases correctly on exception. So the isFlushingEvents flag is the only thing that gets stuck. But InterruptedException from publishEvents() is a real path that could trigger this in practice.
Suggested Fix
Wrap the publish loop in a try/finally:
isFlushingEvents = true;
try {
for (FlushPayload payload : flushPayloads) {
eventCount += payload.eventCount;
publishEvents(this.sdkKey, payload);
}
} finally {
isFlushingEvents = false;
}
Context
Found during a cross-SDK audit related to dotnet-server-sdk #204, which fixed a flush-mutex-leak in the .NET SDK where
EndFlush()wasn't called if the WASM bucketing engine threw. That audit flagged a related (but distinct) issue here.Problem
In
EventQueueManager.java,flushEvents()setsisFlushingEvents = truebefore the publish loop andisFlushingEvents = falseafter — but not in afinallyblock:publishEvents()declaresthrows InterruptedException. If that exception escapes,isFlushingEventsstaystruefor the lifetime of the process. Every subsequent call toflushEvents()returns early at line 70:Events accumulate and are never sent.
Severity: Low.
getResponse()catchesIOExceptionand returns 500, and thesynchronizedonflushEvents()means the JVM mutex releases correctly on exception. So theisFlushingEventsflag is the only thing that gets stuck. ButInterruptedExceptionfrompublishEvents()is a real path that could trigger this in practice.Suggested Fix
Wrap the publish loop in a
try/finally: