- Update KNOWN_ISSUES.md to reflect the mitigation of goroutine leaks and reduced memory growth, detailing the current status and residual behaviors. - Enhance the state worker lifecycle in manager.go to ensure proper command processing and cleanup. - Implement a safe three-step shutdown sequence in trace.go for the Release function, improving resource management and preventing premature exits. - Adjust memory leak test thresholds in KNOWN_ISSUES.md to accommodate improved performance metrics.
3.5 KiB
Trace Module - Known Issues
This document tracks known issues in the Trace module that are scheduled for refactoring.
Goroutine Leak (Mitigated)
Symptom
Each trace creation starts 2 goroutines that accumulate during rapid iterations:
trace/pubsub.(*PubSub).forward()- PubSub event forwardingtrace.(*manager).startStateWorker()- State machine worker
Current Status
Fixed in Feb 2026: State worker now uses for range on the command channel,
which exits cleanly when Release() closes the channel. The three-step shutdown
sequence (atomic flag -> cancel -> close) ensures:
- No new commands are accepted after the flag is set
- In-flight
safeSendcalls unblock viactx.Done - Worker drains remaining buffered commands before exiting
Residual Behavior
- PubSub
forward()goroutine still exits asynchronously afterStop()closes its channel - In rapid create/release loops, there may be a brief overlap where old goroutines haven't exited before new ones start. This is normal Go async cleanup behavior.
- NOT a true leak: goroutines eventually exit (channels are closed)
Impact on Tests
Memory leak tests use a 20KB/iteration threshold to accommodate this overhead:
| Test | Actual Growth | Threshold |
|---|---|---|
| StandardMode | ~15 bytes/iter | 20 KB |
| BusinessScenarios | ~80 bytes/iter | 20 KB |
| NestedCalls | ~13 KB/iter | 20 KB |
Memory Growth (Reduced)
Symptom
Linear memory growth during trace operations.
Current Status
Improved in Feb 2026: The state worker lifecycle fix eliminates the scenario where the worker exits prematurely while the channel remains open, which could cause command objects to accumulate in the buffer without being consumed.
The three-step shutdown ensures all buffered commands are processed before the worker exits, reducing memory retention from unconsumed channel entries.
Residual Growth Sources
- PubSub subscription objects (cleaned up on Stop)
- Driver I/O buffers (transient, GC-eligible)
- Trace node references in memory state (released on worker exit)
Workaround
The 20KB threshold in memory leak tests accommodates known overhead while still detecting severe leaks (50KB+ growth would indicate a real problem).
Planned Refactoring
The Trace module is scheduled for further refactoring:
- Global Event Service: Decouple event broadcasting from trace manager into a process-level daemon (separate plan)
- Resource pooling: Consider reusing trace resources to reduce allocation overhead
- PubSub synchronous cleanup: Ensure forward() goroutine exits before Stop() returns
Testing Notes
When running memory leak tests:
TestMemoryLeakStandardMode: 20KB thresholdTestMemoryLeakBusinessScenarios: 20KB thresholdTestMemoryLeakNestedCalls: 20KB thresholdTestMemoryLeakNestedConcurrent: 25KB threshold (concurrent + DB operations)
These thresholds are intentionally higher than actual growth to:
- Accommodate CI environment variations
- Allow for GC timing differences
- Still catch severe leaks (50KB+ would be concerning)
Related Files
trace/manager.go- State machine and goroutine managementtrace/state.go- Channel-based state worker and safeSendtrace/trace.go- Release() three-step shutdowntrace/pubsub/pubsub.go- PubSub forwarding goroutinetrace/trace_lifecycle_test.go- Boundary condition tests for shutdown racestrace/BUGFIX.md- Detailed bug analysis and fix documentation
Last updated: February 2026