Node: worker threads removelistener in callback, can't emit event again

Created on 30 Jun 2020  Â·  4Comments  Â·  Source: nodejs/node

  • Version: v14.2.0/v12.16.1
  • Platform: Darwin admins-MacBook-Pro.local 19.0.0 Darwin Kernel Version 19.0.0: Fri Oct 11 19:41:52 PDT 2019; root:xnu-6153.41.3~8/RELEASE_X86_64 x86_64
  • Subsystem:

What steps will reproduce the bug?


there are two file, and command node main.js:

// main.js
(async () => {
    const {
        Worker
    } = require('worker_threads')
    const worker = new Worker(`${__dirname}/worker.js`)


    for (let i = 0; i < 10; i++) {
        await new Promise((resolve, reject) => {
            // Section1: in this valid
            // worker.removeAllListeners();

            worker.on('message', (data) => {
                // Section2: in this invalid
                worker.removeAllListeners();

                console.log(`data ${JSON.stringify(data)}`)
                resolve(data)
            })

            worker.postMessage({
                param: i
            })
        })
    }
})()
// worker.js
const {
    parentPort
} = require('worker_threads')


parentPort.on('message', async (data) => {
    console.log(`worker on message: ${JSON.stringify(data)}`)

    parentPort.postMessage(data)
})

How often does it reproduce? Is there a required condition?

when i run node main.js, you can see the result

What is the expected behavior?

worker on message: {"param":0}
data {"param":0}
worker on message: {"param":1}
data {"param":1}
worker on message: {"param":2}
data {"param":2}
worker on message: {"param":3}
data {"param":3}
worker on message: {"param":4}
data {"param":4}
worker on message: {"param":5}
data {"param":5}
worker on message: {"param":6}
data {"param":6}
worker on message: {"param":7}
data {"param":7}
worker on message: {"param":8}
data {"param":8}
worker on message: {"param":9}
data {"param":9}

What do you see instead?

worker on message: {"param":0}
data {"param":0}
worker on message: {"param":1}

Additional information


when i use this line will be ok:

// in this valid
// worker.removeAllListeners();
wontfix worker

Most helpful comment

I think this is happening because the Worker class manages its lifetime through 'newListener' and 'removeListener' listeners which check the presence of 'message' listeners. Using .removeAllListeners() removes those internal listeners as well.

That underlying problem isn’t specific to Workers – you’d run into the same problem with other parts of Node.js as well.

I’ll ping @nodejs/workers, but if nobody feels strongly about this (and has a good idea for how to do so), I’d close this as wontfix.

All 4 comments

I think this is happening because the Worker class manages its lifetime through 'newListener' and 'removeListener' listeners which check the presence of 'message' listeners. Using .removeAllListeners() removes those internal listeners as well.

That underlying problem isn’t specific to Workers – you’d run into the same problem with other parts of Node.js as well.

I’ll ping @nodejs/workers, but if nobody feels strongly about this (and has a good idea for how to do so), I’d close this as wontfix.

I agree with wontfix . My reason: The document for removeAllListerner is clear in terms of side effects: https://nodejs.org/dist/latest-v14.x/docs/api/events.html#events_emitter_removealllisteners_eventname - It is bad practice to remove listeners added elsewhere in the code...

I don't know why i use removeALlListener in Setion1, it will be ok and listener will be trigger again. What's the difference ?

@JianmingXia I think it depends on whether you remove the listeners while the Worker object is having .on('message') listeners or not.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Brekmister picture Brekmister  Â·  3Comments

danielstaleiny picture danielstaleiny  Â·  3Comments

willnwhite picture willnwhite  Â·  3Comments

mcollina picture mcollina  Â·  3Comments

dfahlander picture dfahlander  Â·  3Comments