Skip to content

fix(connect): make timeout cover the STOMP handshake (fix hung-CONNECT socket leak)#138

Open
amilcarsilvestre wants to merge 1 commit into
gdaws:masterfrom
amilcarsilvestre:fix/connect-timeout-covers-stomp-handshake
Open

fix(connect): make timeout cover the STOMP handshake (fix hung-CONNECT socket leak)#138
amilcarsilvestre wants to merge 1 commit into
gdaws:masterfrom
amilcarsilvestre:fix/connect-timeout-covers-stomp-handshake

Conversation

@amilcarsilvestre

Copy link
Copy Markdown

Make connect timeout cover the STOMP handshake (fix hung-CONNECT socket leak)

Fixes #137.

Problem

The timeout option of connect() only covered the transport (TCP/TLS) connect. onConnected() (fired on transport connect) called cleanup() — which clearTimeout(timeout)before running the STOMP CONNECTCONNECTED handshake. So a server that accepts the socket but never returns CONNECTED left the connection hung with no timeout and the socket open indefinitely (the callback never fires, and heartbeats are only armed after CONNECTED).

Change

In lib/connect.js, onConnected() no longer clears the timeout. It removes only the transport-level listeners and keeps the timeout armed while client.connect(...) performs the STOMP handshake; the timeout is cleared when the handshake completes or errors (via a wrapper around connectListener). If the handshake stalls, the existing timeout handler fires client.destroy('connect timed out'), which closes the socket and surfaces the error to the callback.

Behavior change: timeout now bounds the whole connect (transport + STOMP handshake), which matches what a "connect timeout" is expected to mean. No API change.

Test

Added a test: a fake transport that connects but never sends CONNECTED must cause connect() to error within timeout and destroy the socket (no leak).

The connect `timeout` only covered the transport (TCP/TLS) connect: it was
cleared in onConnected (on transport connect) before the STOMP
CONNECT/CONNECTED handshake ran, and that handshake had no timeout of its own
(heartbeats are only armed after CONNECTED). A server that accepts the socket
but never sends CONNECTED left the connection hung forever, with the socket
open and the callback never invoked.

Keep the timeout armed until the handshake settles (cleared in a wrapped
connectListener). A stalled handshake now triggers client.destroy('connect
timed out'), closing the socket and surfacing an error to the callback.
timeout now bounds the whole connect (transport + handshake). Adds a
regression test.

Co-Authored-By: Claude <noreply@anthropic.com>
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.

connect timeout does not cover the STOMP handshake — a stalled CONNECT leaks the socket

1 participant