-
Notifications
You must be signed in to change notification settings - Fork 29.7k
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
Module Hooks cannot be registered from worker thread in 22.2.0+ #53182
Comments
Hi @ShogunPanda,
const { register } = require("node:module");
const { pathToFileURL } = require("node:url");
const { Worker } = require("worker_threads");
register("./hooks.mjs", pathToFileURL(__filename));
new Worker("./lib/child.js"); and then Would that work in your case? |
The title of this issue seems wrong, if it's about registering from a worker thread. |
@targos It was a mental typo. Fixed. Thanks. |
@dygabo I can see that, but the problem is that the process hangs rather than immediately throwing an exception. |
@nodejs/loaders |
So there are two solutions that I can think of:
I think the second solution is much preferable to the first, unless we can’t achieve it for some reason. The first could be a stopgap temporary solution, better than a hang and arguably better than the incorrect behavior before #52706, but it still kind of sucks as I think we would agree that it’s not our intended final design. Ideally we can just go straight to the second solution and skip over any stopgaps like the exception or a revert. @dygabo and @ShogunPanda, how feasible is the second solution? Is this something that we could potentially get a PR for in the next few days? |
The bug is a bit more nuanced: the hang only happens when calling const { Worker } = require("worker_threads");
new Worker("./lib/child.js"); And then change require("./register");
require("./local"); The process no longer hangs. The This doesn’t really change the analysis of my previous comment; ideally |
this needs attention and probably also some time to get the edge cases right. I cannot promise a few days so if this is important, please consider the revert. I can look into it (going for solution no 2.). |
I think the intended behavior, where there’s only ever one hooks thread and it applies to all application threads, is the base we need to ship. That’s the use case of “I’m writing an application in TypeScript, and my app has worker threads. I want to be able to write my entire app in TypeScript, including the worker threads, with minimal overhead.” Forcing one hooks thread per application thread all the time is a performance hit for most users. We could permit that as an alternative mode that users can enable somehow, but that’s a feature request that we can discuss once we get the intended behavior working. @ShogunPanda I think there are (at least) two issues here:
I think perhaps this issue should focus on the first one, and a new issue could be opened for the latter? Since I assume you’re mostly concerned about the hang introduced in 22.2.0. |
@GeoffreyBooth Agreed: if we solve the hang we might not need the revert so quickly. But I don't really see the no-op as a long time solution |
I just meant that the noop is a separate bug, since it predates 22.2.0. But maybe we can solve both together. |
Oh, I see! Yes, I hope we can fix it both at the same time. |
To make it easier for people to get into the history of this: PR which introduced the loader thread: #44710 FWIW the question one thread for all or one per worker was already there: #43658 (comment) and that time it was one per thread (see here). Similar in the PR (e.g. here). Is there somewhere a condensed decission finding document from that time? |
See https://github.com/nodejs/loaders#milestone-1-parity-with-commonjs
|
See the very next comment: #43658 (comment)
Meeting notes: nodejs/loaders#118 (comment) |
I don't know if this is the appropriate place to comment but I think I discovered another issue with the common hooks thread and workers. In a worker it is possible to override the import conditions of the parent thread. e.g. // Main.js
const worker = new Worker("MyWorker.js", {
execArgv: ["--conditions", "foo"]
}); However, the module hooks appear to always use the conditions of the main thread. e.g. when starting a script with conditions that spawns a worker with different conditions:
The worker conditions will be ignored by the module hooks and the conditions of the main thread will be applied. |
|
@GeoffreyBooth Thanks for linking that issue. I was loosing my mind 😅 |
Should be fixed by #53183, please reopen if not. |
Version
v22.2.0
Platform
Darwin panda.local 23.4.0 Darwin Kernel Version 23.4.0: Fri Mar 15 00:12:49 PDT 2024; root:xnu-10063.101.17~1/RELEASE_ARM64_T6020 arm64
Subsystem
module
What steps will reproduce the bug?
Create the following files:
index.js
lib/register.js
Then execute:
node index.js
How often does it reproduce? Is there a required condition?
Always.
What is the expected behavior? Why is that the expected behavior?
The worker thread should start with the hooks register successfully.
What do you see instead?
The process hangs.
Removing the
register
call will solve the problem.Additional information
This problem happens due to #52706, as already triaged in #53097.
An additional problem is that the suggested workaround forces people to use
node --import register.js
in order to solve the problem as the module thread is shared with Workers.While this is fine, there might be situation in which users cannot use
--import
(or--require
).In those situation I have observed the
register
call will successfully work for subsequent dynamicimport()
call but NOT forrequire()
(unless I missed something obvious).I created https://github.com/ShogunPanda/hooks-repro to reproduce this.
The text was updated successfully, but these errors were encountered: