Skip to content

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

Description

@amilcarsilvestre

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

Summary

stompit.connect(options, cb) accepts a timeout option (default 3000 ms), but that timeout only covers the transport connect (TCP / TLS). It is cleared the moment the transport connects, before the STOMP CONNECTCONNECTED handshake runs. As a result, if a server accepts the TCP/TLS socket but never replies with a CONNECTED frame (e.g. an overloaded broker), the returned promise/callback never fires, no timeout ever triggers, and the underlying socket stays open forever. Because connect() returns the client synchronously but the callback never runs, a caller using only the callback has no handle to the leaked socket.

Where

lib/connect.js:

  • The single timeout is armed at socket = transportConnect(...) (covers transport).
  • onConnected() (fires on transport connect) calls cleanup(), which does clearTimeout(timeout)canceling the timeout — and only then calls client.connect(connectOpts, connectListener) to perform the STOMP handshake.
  • client.connect waits for CONNECTED with no timeout. Heartbeats are only armed after CONNECTED is received, so they don't help either.

Impact

Any consumer that keeps connecting (especially a long-running service with reconnect logic) against a broker that stalls the STOMP handshake will accumulate half-open sockets. In our case a long-running consumer facing an overloaded ActiveMQ ended up with 10,000+ simultaneous connections, saturating the broker. Even a simple client just hangs indefinitely instead of getting a connect timeout.

Expected

The timeout option should bound the entire connect, including the STOMP handshake — a stalled CONNECT should time out, client.destroy(...) the socket, and surface an error to the callback.

Repro (conceptual)

Point stompit.connect at a TCP server that accepts the socket and never sends a STOMP CONNECTED frame. Observe: the callback never fires and the socket remains open past timeout.

Fix

Keep the connect timeout armed until the STOMP handshake completes (or errors), instead of clearing it when the transport connects. PR attached.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions