Skip to content

fix: clean up socket.acks on broadcastWithAck timeout#5452

Open
veeceey wants to merge 1 commit intosocketio:mainfrom
veeceey:fix/issue-4984-emitWithAck-memory-leak
Open

fix: clean up socket.acks on broadcastWithAck timeout#5452
veeceey wants to merge 1 commit intosocketio:mainfrom
veeceey:fix/issue-4984-emitWithAck-memory-leak

Conversation

@veeceey
Copy link

@veeceey veeceey commented Feb 14, 2026

Fixes #4984

When using emitWithAck with a timeout on broadcast operations (e.g. io.timeout(2000).to("room").emitWithAck("event", data)), the ack callbacks stored in each socket's acks map were never removed if the client didn't respond before the timeout.

This causes a memory leak because socket.acks.set(packet.id, ack) is called in broadcastWithAck for every target socket, but when the timeout fires in broadcast-operator.ts, only the caller-side ack gets invoked - the per-socket entries in socket.acks are left behind indefinitely.

The fix tracks which sockets received the broadcast ack and schedules cleanup of their acks entries after the timeout period. This matches the existing pattern in registerAckCallback on individual sockets, which already cleans up on timeout (line 324 of socket.ts).

The issue is straightforward to reproduce: broadcast emitWithAck to a room where clients never call the callback, and observe that socket.acks grows unboundedly. The reporter measured 1.5 GB after 3 hours with 500 clients.

Includes unit tests verifying:

  • ack entries are cleaned up after timeout expires
  • no cleanup timer is set when timeout is not specified

When using emitWithAck with a timeout on broadcast operations, the ack
callbacks stored in each socket's acks map were never cleaned up if the
client didn't respond before the timeout fired. Over time this causes
significant memory leaks, especially with many sockets and frequent
broadcasts.

The fix tracks which sockets received the broadcast ack and schedules
cleanup of their acks map entries after the timeout period, matching
the behavior already present in individual socket registerAckCallback.

Fixes socketio#4984
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"emitWithAck" function leaks memory when acknowledgement timeout

1 participant