Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

node:worker_threads doesn't support MessagePort in workerData #22935

Closed
bartlomieju opened this issue Mar 14, 2024 · 1 comment · Fixed by #22950
Closed

node:worker_threads doesn't support MessagePort in workerData #22935

bartlomieju opened this issue Mar 14, 2024 · 1 comment · Fixed by #22950

Comments

@bartlomieju
Copy link
Member

bartlomieju commented Mar 14, 2024

Version: Deno 1.41.3

In #22815 we got rid of raciness in worker setup code, but unfortunately now it's not possible to pass MessagePort in workerData and transferList options.

Doing so results in BadResource error when one tries to use the port: #22911 (comment)

Ref #22911

@bartlomieju
Copy link
Member Author

Minimal reproduction:

// worker.mjs
import {
  isMainThread,
  MessageChannel,
  parentPort,
  receiveMessageOnPort,
  Worker,
  workerData,
} from "node:worker_threads";

if (isMainThread) {
  const { port1: mainPort, port2: workerPort } = new MessageChannel();

  // This re-loads the current file inside a Worker instance.
  const w = new Worker(import.meta.filename, {
    workerData: { workerPort },
    transferList: [workerPort],
  });

  w.on("message", (data) => {
    console.log("message from worker", data);

    const msg = receiveMessageOnPort(mainPort).message;
    console.log("message on mainPort", msg);
    w.terminate();
  });

  w.postMessage("Hello from parent");
} else {
  console.log("Inside Worker!");
  parentPort.on("message", (msg) => {
    console.log("message from main", msg);
    parentPort.postMessage("Hello from worker on parentPort!");
    workerData.workerPort.postMessage("Hello from worker on workerPort!");
  });
}
$ node worker.mjs
Inside Worker!
message from worker Hello from worker on parentPort!
message on mainPort Hello from worker on workerPort!
message from main Hello from parent

$ deno run -A worker.mjs
Inside Worker!
# exits
# There's actually a BadResource error raised, but it's swallowed an never surfaced

# With some debug logs
$ ./target/debug/deno run -A worker.mjs
Inside Worker!
parentPort listener called message
before MessagePort.postMessage Error
    at MessagePort.postMessage (ext:deno_web/13_message_port.js:117:52)
    at file:///Users/ib/dev/deno/worker.mjs:32:27
    at _listener (node:worker_threads:456:9)
    at innerInvokeEventListeners (ext:deno_web/02_event.js:754:7)
    at invokeEventListeners (ext:deno_web/02_event.js:801:5)
    at dispatch (ext:deno_web/02_event.js:658:9)
    at dispatchEvent (ext:deno_web/02_event.js:1043:12)
    at pollForMessages (ext:runtime_main/js/99_main.js:313:7)
    at eventLoopTick (ext:core/01_core.js:169:7)
before MessagePort.postMessage op 4
before get in op_message_port_message
after get  in op_message_port_message CustomError {
    class: "BadResource",
    message: "Bad resource ID",
}
after worker thread loop
error: Uncaught (in worker "") BadResource: Bad resource ID
    workerData.workerPort.postMessage("Hello from worker on workerPort!");
                          ^
    at MessagePort.postMessage (ext:deno_web/13_message_port.js:148:5)
    at file:///Users/ib/dev/deno/worker.mjs:32:27
    at _listener (node:worker_threads:456:9)
    at innerInvokeEventListeners (ext:deno_web/02_event.js:754:7)
    at invokeEventListeners (ext:deno_web/02_event.js:801:5)
    at dispatch (ext:deno_web/02_event.js:658:9)
    at dispatchEvent (ext:deno_web/02_event.js:1043:12)
    at pollForMessages (ext:runtime_main/js/99_main.js:313:7)
    at eventLoopTick (ext:core/01_core.js:169:7)
error: Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'message')
    const msg = receiveMessageOnPort(mainPort).message;
                                              ^
    at NodeWorker.<anonymous> (file:///Users/ib/dev/deno/worker.mjs:22:47)
    at NodeWorker.emit (ext:deno_node/_events.mjs:383:28)
    at NodeWorker.#pollMessages (node:worker_threads:310:12)
    at eventLoopTick (ext:core/01_core.js:169:7)

bartlomieju added a commit that referenced this issue Mar 16, 2024
)

This commit fixes passing `MessagePort` instances to
`WorkerOptions.workerData`.

Before they were not serialized and deserialized properly when spawning
a worker thread.

Closes #22935
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant