sindresorhus/public-ip

DNS query timeout blocks CLI application

pmuens opened this issue ยท 6 comments

I'm currently using public-ip in a CLI application.

I want the IP fetching to silently fail when something went wrong. However forcing an error (to test this behavior) yields to a blocked CLI (the CLI is unresponsive and hangs).

Here's the code I've used:

const getV4Address = (data) => {
      const timeout = 5; // used to force an error

      return address.v4({ timeout })
        .then(ip => data.ipV4Address = ip) //eslint-disable-line
        .catch((error) => {
          console.log(error); // this is used to see why the CLI hangs.

          return Promise.resolve();
        });
};

and here's the error message I get when I log it:

Error: Query timed out
    at DNS._ontimeout (/app/node_modules/dns-socket/index.js:98:18)
    at Timeout.ontimeout [as _onTimeout] (/app/node_modules/dns-socket/index.js:52:10)
    at ontimeout (timers.js:365:14)
    at tryOnTimeout (timers.js:237:5)
    at Timer.listOnTimeout (timers.js:207:5)

Thanks in advance!

I guess something is keeping the event loop alive (despite socket.destroy() being called) longer than is necessary.

Do you also see it with the https option?

Thanks for following up @silverwind ๐Ÿ‘

Hmm. Interesting. The CLI won't be blocked when using the https option. It just prints the following error and then exits:

const getV4Address = (data) => {
      const timeout = 5; // used to force an error

      return address.v4({ timeout, https: true })
        .then(ip => data.ipV4Address = ip) //eslint-disable-line
        .catch((error) => {
          console.log(error); // this is used to see why the CLI hangs.

          return Promise.resolve();
        });
};
{ RequestError
    at ClientRequest.req.once.err (/app/node_modules/public-ip/node_modules/got/index.js:73:21)
    at ClientRequest.g (events.js:292:16)
    at emitOne (events.js:101:20)
    at ClientRequest.emit (events.js:188:7)
    at Timeout.timeoutHandler [as _onTimeout] (/app/node_modules/public-ip/node_modules/timed-out/index.js:16:8)
    at ontimeout (timers.js:365:14)
    at tryOnTimeout (timers.js:237:5)
    at Timer.listOnTimeout (timers.js:207:5)
  code: 'ETIMEDOUT',
  message: 'Connection timed out on request to ipv4.icanhazip.com',
  host: 'ipv4.icanhazip.com',
  hostname: 'ipv4.icanhazip.com',
  method: 'GET',
  path: '/' }

You could try using https://github.com/mafintosh/why-is-node-running to see what's blocking.

Found the issue. We're missing a rejection handler (and socket termination) on the dns request.

Fixed in public-ip@2.3.2.

Awesome! Thanks @silverwind and @sindresorhus ๐ŸŽ‰ ๐Ÿ‘