libp2p/js-libp2p-tcp

`/dnsaddr` multiaddrs in bootstrap list cause stopping a libp2p node to hang forever

achingbrain opened this issue · 3 comments

const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const Bootstrap = require('libp2p-bootstrap')
const MPLEX = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise')
const PeerId = require('peer-id')

async function main () {
  const peerId = await PeerId.create()
  const bootstrapList = [
    '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt',
    '/dns4/node0.preload.ipfs.io/tcp/443/wss/p2p/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic'
  ]

  const node = new Libp2p({
    peerId,
    addresses: {
      listen: []
    },
    modules: {
      transport: [
        TCP
      ],
      streamMuxer: [
        MPLEX
      ],
      connEncryption: [
        NOISE
      ],
      peerDiscovery: [
        Bootstrap
      ]
    },
    config: {
      peerDiscovery: {
        bootstrap: {
          interval: 30e3,
          enabled: true,
          list: bootstrapList
        }
      }
    }
  })

  console.info('starting')
  await node.start()
  console.info('stopping')
  await node.stop()
}

main()
{
  "dependencies": {
    "libp2p": "^0.30.7",
    "libp2p-bootstrap": "^0.12.1",
    "libp2p-mplex": "^0.10.0",
    "libp2p-noise": "^2.0.1",
    "libp2p-tcp": "^0.15.1",
    "peer-id": "^0.14.3"
  }
}
$ node index.js 
starting
stopping   <-- hangs here

Comment out '/dnsaddr/bootstrap.libp2p.io.. or change to '/dns4/bootstrap.libp2p.io... and the process exits as expected.

Does not happen with libp2p-websockets as a transport, only libp2p-tcp.

Interesting, this might be related to libp2p/js-libp2p#779

I will try to book some time to debug this today/tomorrow

Looking into this, the node is in theory stopped as the the stop promise is resolved. However, the ongoing dials are not being properly stopped, which ends up with the process hanging as libp2p/js-libp2p#779

The difference of using /dnsaddr seems to be that it will result in a set of other addresses to dial and the dial queue will be working when the stop happens.

What is happening is:

So, what we basically need is to make the resolve abortable, keep a record of the on going resolves and abort all of them on Dialer.destroy

@achingbrain I am going to close this issue and get the information cross posted in the libp2p onde