Skip to content

worker_thread can not capture promise error in worker #33834

Closed

Description

@lanjia
  • Version 12.18:
  • Platform ox 10.15.5:
  • Subsystem:

What steps will reproduce the bug?

const { Worker, isMainThread } = require('worker_threads')

if (isMainThread) {
  const fn = () => {
    return new Promise((resolve, reject) => {
      const worker = new Worker(__filename)
      worker.on('message', resolve)
      worker.on('error', reject)
      worker.on('exit', (code) => {
        if (code !== 0)
          reject(new Error(`Worker stopped with exit code ${code}`))
      })
    })
  }
  (async () => {
    try {
      await fn()
    } catch (err) {
      console.log('main thread err:', err.message)
    }
  })()
} else {
  (async () => {
    throw new Error('worker thread err')
  })()
}

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

What is the expected behavior?

[Running] node "/code/test/workthread.js"
(node:58339) UnhandledPromiseRejectionWarning: Error: worker thread err
    at /code/test/workthread.js:24:11
    at Object.<anonymous> (/code/test/workthread.js:25:5)
    at Module._compile (internal/modules/cjs/loader.js:1200:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1220:10)
    at Module.load (internal/modules/cjs/loader.js:1049:32)
    at Function.Module._load (internal/modules/cjs/loader.js:937:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at MessagePort.<anonymous> (internal/main/worker_thread.js:167:24)
    at MessagePort.emit (events.js:315:20)
    at MessagePort.onmessage (internal/worker/io.js:78:8)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:58339) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:58339) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

[Done] exited with code=0 in 0.081 seconds

What do you see instead?

Additional information

Activity

  1. benjamingr commented on Jun 11, 2020

    @benjamingr
    Member

    This behavior is by design and is how Node.js handles rejections. You probably want to use --unhandled-rejections=strict or add a process.on('unhandledRejection' handler.

    For what it's worth this behavior is currently being discussed ( nodejs/TSC#857 )

    I'm going to leave this open in case @addaleax has something to add here. Potentially we could dispatch unhandledRejection or error on the worker as well or something similar - but that would diverge from the rest of the project.

  2. added
    promisesIssues and PRs related to ECMAScript promises.
    workerIssues and PRs related to the worker_threads module and Worker API.
    on Jun 11, 2020
  3. lundibundi commented on Jun 11, 2020

    @lundibundi
    Member

    The behavior is by design and it is possible to capture unhandled rejection in worker threads.
    This is done the same way as for main thread, by capturing unhandledRejection event. If you change you worker code to

      process.on('unhandledRejection', promise => {
        process.exit(42);
      });
      (async () => {
        throw new Error('worker thread err')
      })()

    it will finish the worker upon receiving unhandledRejection and you will get that error in worker.on('exit', (code) => { handler. Another option is to just report it via 'message'.

    As for the

    Potentially we could dispatch unhandledRejection or error

    IMO this will have to wait on a general agreement for the default behavior of unhandledRejection's (whether to exit the process by default), otherwise, it will introduce potentially unnecessary differences between main thread and worker threads.
    Though we could add an option to automatically add such a handler in worker options that would report/error/exit depending on the option.

  4. addaleax commented on Jun 11, 2020

    @addaleax
    Member

    I'm going to leave this open in case @addaleax has something to add here.

    Though we could add an option to automatically add such a handler in worker options that would report/error/exit depending on the option.

    We have that option already – using this instead of new Worker(__filename) “fixes” it:

    const worker = new Worker(__filename, {
      execArgv: [...process.execArgv, '--unhandled-rejections=strict' ]
    })
  5. benjamingr commented on Jun 13, 2020

    @benjamingr
    Member

    I think this can be closed. @lanjia thank you for the report :] Please feel free to open more issues about behaviors you find surprising in worker_threads we appreciate those!

    (As usual, if anyone feels strongly about this or that we should keep discussing - feel free to re-open)

  6. TimDaub commented on Apr 22, 2021

    @TimDaub

    We have that option already – using this instead of new Worker(__filename) “fixes” it:

    IMO, this should be default behavior. It's been weeks that I've been confused with the "worker_threads" implementations and why sometimes it just finishes without logging anything. The problem was most of the time that uncaught exceptions are thrown but never reported.

  7. addaleax commented on Apr 22, 2021

    @addaleax
    Member

    We have that option already – using this instead of new Worker(__filename) “fixes” it:

    IMO, this should be default behavior.

    @TimDaub It is the default behavior in Node.js 15+.

  8. TimDaub commented on Apr 22, 2021

    @TimDaub

    @TimDaub It is the default behavior in Node.js 15+.

    that's great! Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    promisesIssues and PRs related to ECMAScript promises.workerIssues and PRs related to the worker_threads module and Worker API.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions