Skip to content

fix(tracing/worker): getOrCreateTrace can resurrect a Trace into a cleared sessionTraces map on workspace switch #902

@anandgupta42

Description

@anandgupta42

Found during the v0.8.4 release review (Chaos Gremlin persona). Deferred — rare concurrency edge, needs careful design + a deterministic test, >30 min.

Problem

#895 made getOrCreateTrace (worker.ts) async (it now awaits rehydrateFromFile). The within-stream for await loop is sequential, so same-stream reentrancy is not the issue. The issue is cross-handler: a setWorkspace RPC can run while the event loop is parked at await getOrCreateTrace(...). On a genuine workspace change, startEventStream calls eventStream.abort.abort() then sessionTraces.clear() synchronously. When the parked loop resumes, it runs Trace.setActive(trace) + sessionTraces.set(sessionID, trace) into the freshly-cleared map — resurrecting a Trace under a stream that's supposed to be dead (orphaned writer).

Impact

Bounded: only on a real workspace switch (rare). On-disk file content stays correct (keyed by sessionID). The defect is a leaked/duplicate in-memory Trace writing after its stream was aborted.

Proposal

After the await in getOrCreateTrace, re-check currency before committing to the map: if sessionTraces was cleared or the stream's abort signal fired while suspended, drop the freshly-built Trace (void trace.endTrace().catch(()=>{})) instead of inserting it.

Acceptance

  • A setWorkspace-driven clear that interleaves with a suspended getOrCreateTrace does not leave an entry in sessionTraces tied to the aborted stream.
  • Deterministic test simulating the interleave (Dispatcher/spyOn, no mock.module).

Refs: #895

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions