Problem
tools/mcp/trinity_mcp/websocket_transport.zig has a memory leak in the handleConnection() loop. When parseFrame() processes a masked WebSocket frame, it allocates memory for the unmasked payload (line ~250: const unmasked = try self.allocator.alloc(u8, payload_len)). But after the switch statement processes the frame, the payload is never freed.
File
tools/mcp/trinity_mcp/websocket_transport.zig
Lines to fix
Around lines 130-169 in handleConnection():
- Line ~130:
const frame = self.parseFrame(buffer[0..n]) — may allocate payload
- Lines ~136-168: switch processes frame but never frees payload
- Need to add
defer to free allocated payload after use
Fix
Add a defer statement after the frame is successfully parsed to free the payload when it was allocated:
const frame = self.parseFrame(buffer[0..n]) catch |err| {
// ... error handling
};
// Add this line to prevent memory leak:
defer if (frame.allocated) self.allocator.free(frame.payload);
If parseFrame doesn't have an allocated flag, you may need to check the approach. One option: always free payload if it's not a slice of the input buffer. Another option: add a boolean field to Frame indicating whether payload was allocated.
The simplest approach may be to track whether parseFrame allocated by comparing the payload pointer to the input buffer range.
Acceptance
zig build compiles
- Frame payload is freed after each iteration of the handleConnection loop
- No memory leak on masked WebSocket frames
Problem
tools/mcp/trinity_mcp/websocket_transport.zighas a memory leak in thehandleConnection()loop. WhenparseFrame()processes a masked WebSocket frame, it allocates memory for the unmasked payload (line ~250:const unmasked = try self.allocator.alloc(u8, payload_len)). But after the switch statement processes the frame, the payload is never freed.File
tools/mcp/trinity_mcp/websocket_transport.zigLines to fix
Around lines 130-169 in
handleConnection():const frame = self.parseFrame(buffer[0..n])— may allocate payloaddeferto free allocated payload after useFix
Add a defer statement after the frame is successfully parsed to free the payload when it was allocated:
If
parseFramedoesn't have anallocatedflag, you may need to check the approach. One option: always free payload if it's not a slice of the input buffer. Another option: add a boolean field to Frame indicating whether payload was allocated.The simplest approach may be to track whether parseFrame allocated by comparing the payload pointer to the input buffer range.
Acceptance
zig buildcompiles