Skip to content

Socket connection timeouts don't fire #1523

@damons-sportsbet

Description

@damons-sportsbet
  • I've searched for any related issues and avoided creating a duplicate
    issue.

Description

Setting a handshake timeout for a connection doesn't work if the socket never connects.

I want my app to fail fast if it can't connect to an endpoint, but I found that if I set a handshakeTimeout of 5 seconds and configured my app to talk to a known machine but on a port that just silently drops connecting packets, then it didn't time out in 5 seconds but instead would get a global ETIMEDOUT error.

Looking at the code for websocket.js it does this:

var req = (this._req = httpObj.get(options));

  if (options.handshakeTimeout) {
    req.on('timeout', () => {
      abortHandshake(this, req, 'Opening handshake has timed out');
    });
}

but I note that the advice for this is to wait for a socket to be assigned before setting a timeout handler. Testing this myself, I also found that just waiting for a socket wasn't enough to get the https library to handle the timeout properly, I had to also set an empty socket timeout handler on the socket itself.

So if I rewrite the code above as:

	this._req = httpObj.get(requestOptions)

	this._req.on("socket", socket => {
		if (options.handshakeTimeout) {
			this._req.setTimeout(options.handshakeTimeout, () => {
				this._req.abort()
				this.finalize(new Error("opening handshake has timed out"))
			})
			socket.setTimeout(options.handshakeTimeout, () => {
				// no-op - just causes above request setTimeout to work
			})
		}
	})

(bearing in mind you appear to have made the req var local between my version and HEAD) then I get successful 5 second timeout errors from websockets.

If you like I can make a PR for the change, I just want to make sure it's not some platform dependent issue or other strange workaround.

Thanks!

Reproducible in:

  • version: 6.1.3
  • Node.js version(s): 10.9.0
  • OS version(s): MacOS 10.13.6

Steps to reproduce:

  1. Create a Websockets instance connecting to a known machine and port that drops packets

  2. Set a handshakeTimeout of 5 seconds

  3. Set a timeout handler and see that it does not time out in 5 seconds but instead waits the minute or two for the global error handler to fire.

Expected result:

Timeout handler to fire

Actual result:

no timeout fired

Attachments:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions