Skip to content

cluster: fix edge cases that throw ERR_INTERNAL_ASSERTION

Some cases use both cluster and net/cluser will throw ERR_INTERNAL_ASSERTION when listen/bind to the port of 0, like below:

const cluster = require('cluster')
const dgram = require('dgram')

const kPort = 0;

function child() {
  for (let i = 0; i < 2; i += 1) {
    const socket = new dgram.Socket('udp4')
    socket.bind(kPort)
    setTimeout(() => {
      socket.close()
      const socket2 = new dgram.Socket('udp4')
      socket2.bind(kPort);
    }, 100)
  }
}

if (cluster.isMaster) {
  cluster.fork(__filename)
} else {
  child()
}

would throw:

internal/assert.js:14
    throw new ERR_INTERNAL_ASSERTION(message);
    ^

Error [ERR_INTERNAL_ASSERTION]: This is caused by either a bug in Node.js or incorrect usage of Node.js internals.
Please open an issue with this stack trace at https://github.com/nodejs/node/issues

    at assert (internal/assert.js:14:11)
    at SharedHandle.add (internal/cluster/shared_handle.js:28:3)
    at queryServer (internal/cluster/master.js:309:10)
    at Worker.onmessage (internal/cluster/master.js:249:5)
    at ChildProcess.onInternalMessage (internal/cluster/utils.js:47:8)
    at ChildProcess.emit (events.js:326:22)
    at emit (internal/child_process.js:906:12)
    at processTicksAndRejections (internal/process/task_queues.js:81:21) {
  code: 'ERR_INTERNAL_ASSERTION'
}

After some investigation, I believe it's because we remove the indexesKey when close servers while it might reference more than one index:

https://github.com/nodejs/node/blob/8b8620d580314050175983402dfddf2674e8e22a/lib/internal/cluster/child.js#L127

This PR maitains a separate map of the index to fix the issue.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines

Merge request reports

Loading