ESM Hook deadlocks since 21.2.0 a3e09b3
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- JavaScript
- Star
- 122k
- Fork
- 37.4k
- Merge trung bình
- 4 ngày 3 giờ
- Pull request đã merge (30 ngày)
- 272
Mô tả
Version
21.2.0
Bisected to a3e09b3fdd3908a6cc82afa319596d3889513a51
Platform
Darwin moxy.lan 23.1.0 Darwin Kernel Version 23.1.0: Mon Oct 9 21:27:24 PDT 2023; root:xnu-10002.41.9~6/RELEASE_ARM64_T6000 arm64
Subsystem
esm hooks
What steps will reproduce the bug?
echo 'console.log("hello")' > x.js
echo '{}' > package.json
npm i tap
node --import=./node_modules/@tapjs/mock/dist/esm/import.mjs --import=./node_modules/@tapjs/processinfo/dist/esm/import.mjs x.js
How often does it reproduce? Is there a required condition?
Always reproduces
What is the expected behavior? Why is that the expected behavior?
Expect that it loads the two import arguments, and then runs the file.
What do you see instead?
Deadlocks at the Module.register() call in the second import script.
Additional information
Discussion from slack:
isaacs
7 hours ago
@aduh95
Since a3e09b3fdd3908a6cc82afa319596d3889513a51 landed, node-tap hangs whenever I run it. It seems like it's getting stuck at:
// Sleep until worker responds.
AtomicsWait(this.#lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, this.#workerNotificationLastId);
I haven't been able to narrow it down to a satisfyingly minimal reproduction, and for extra 😬 it's order-dependent, but this will reproduce it in any project that has the latest tap installed:
node --import=./node_modules/@tapjs/mock/dist/esm/import.mjs --import=./node_modules/@tapjs/processinfo/dist/esm/import.mjs x.js
(where x.js is just console.log('hello'))
5 replies
Jacob Smith
4 hours ago
Oof. These are very difficult to troubleshoot.
I think i'll have time on Wednesday to take a look (edited)
aduh95
3 hours ago
For reference: https://github.com/nodejs/node/commit/a3e09b3fdd3908a6cc82afa319596d3889513a51
🙏
1
isaacs
9 minutes ago
It seems like what's going on is that the @tapjs/mock needs to make a request on its MessageChannel port in order to finish its resolve hook.
Then it loads @tapjs/processinfo/import, which calls Module.register. This triggers a sync request to the worker thread for 'register', which then triggers the mock's resolve hook to resolve the loader.mjs file, but because it's already awaiting a sync message (the register), it'll never come, because that sync message is waiting for another sync message (the resolve).
isaacs
4 minutes ago
My working theory at the moment is that it started at the "run imports sequentially" because prior to that, it wasn't blocking on Module.register() so any blocking async-made-sync actions in the process of the register call weren't a problem.
isaacs
1 minute ago
Also: seems like it's related to the use of the MessageChannel specifically. Just a timeout doesn't trigger it, but the busywait message processing seems to keep the other message channel from proceeding.
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Tái hiện deadlock bằng hai script --import và x.js, sau đó kiểm tra đường dẫn Module.register() liên quan đến commit a3e09b3fdd3908a6cc82afa319596d3889513a51. Theo dõi tương tác với AtomicsWait và MessageChannel trong quá trình import tuần tự. Hoàn thành khi cả hai đối số import đều được tải và x.js in ra hello mà không bị treo.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- javascript, node.js
- Lĩnh vực
- backend
- Loại issue
- Lỗi
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 28/100