Skip to content

fix: isFlushingEvents flag can get stuck true if publish loop throws #192

@jonathannorris

Description

@jonathannorris

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;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions