nodejs / nodejs/node

WasmGC cumulative array allocations crash Node.js process with FATAL ERROR instead of trapping

未关闭
#64,981 3 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

blocked v8 engine
主要语言
JavaScript
星标
122k
派生
37.4k
平均合并
4 天 3 小时
30 天内合并 PR
272

描述

Version

24.2.0

Platform
Linux unknown387c76016c42.lan 6.19.14-108.fc42.x86_64 #1 SMP PREEMPT_DYNAMIC Thu May 21 18:06:59 UTC 2026 x86_64 GNU/Linux
Subsystem

No response

What steps will reproduce the bug?
  1. Save the attached exhaust.wat file
  2. Compile: wasm-tools parse exhaust.wat -o exhaust.wasm
  3. Run: node test.js
  4. Process crashes with FATAL ERROR + core dump

exhaust.wat:

(module
  (type $arr (array (mut i64)))
  (type $holder (array (mut (ref null $arr))))

  (func (export "exhaust") (param $count i32)
    (local $h (ref $holder))
    (local $i i32)

    ;; parent array to hold all refs (prevents GC collection)
    (array.new_default $holder (local.get $count))
    (local.set $h)

    (loop $loop
      ;; allocate ~1MB array (131072 x 8 bytes)
      (local.get $h)
      (local.get $i)
      (array.new_default $arr (i32.const 131072))
      (array.set $holder)

      ;; i++
      (local.get $i)
      (i32.const 1)
      (i32.add)
      (local.set $i)

      ;; loop while i < count
      (local.get $i)
      (local.get $count)
      (i32.lt_u)
      (br_if $loop)
    )
  )
)

test.js:

const fs = require('fs');
(async () => {
  const mod = await WebAssembly.compile(fs.readFileSync('exhaust.wasm'));
  const inst = await WebAssembly.instantiate(mod);
  console.log('Allocating 10,000 x 1MB...');
  inst.exports.exhaust(10000);
  console.log('Survived (should not reach here)');
})();
How often does it reproduce? Is there a required condition?

Fully reproducible.

What is the expected behavior? Why is that the expected behavior?

The Wasm module should trap or throw a catchable JavaScript error on GC allocation failure, not crash the process with abort(). Linear memory already handles exhaustion gracefully (memory.grow returns -1), and the WasmGC spec allows implementations to "terminate that computation and report an embedder-specific error" on resource exhaustion.

What do you see instead?

Exit code: 134

Allocating 10,000 x 1MB...

<--- Last few GCs --->

[132127:0x365f6000]     1871 ms: Mark-Compact 4062.8 (4207.1) -> 4062.1 (4207.1) MB, pooled: 1 MB, 5.87 / 0.00 ms  (average mu = 0.944, current mu = 0.848) allocation failure; scavenge might not succeed
[132127:0x365f6000]     1891 ms: Mark-Compact 4095.1 (4240.3) -> 4095.0 (4240.3) MB, pooled: 1 MB, 7.87 / 0.00 ms  (average mu = 0.894, current mu = 0.604) allocation failure; scavenge might not succeed

FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----

 1: 0xf1eeef node::OOMErrorHandler(char const*, v8::OOMDetails const&) [node]
 2: 0x1351da0 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
 3: 0x1351e8f v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
 4: 0x15e8505  [node]
 5: 0x15f968c v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
 6: 0x15cf2f3 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
 7: 0x15a5770 v8::internal::Factory::NewFillerObject(int, v8::internal::AllocationAlignment, v8::internal::AllocationType, v8::internal::AllocationOrigin) [node]
 8: 0x1a98558 v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [node]
 9: 0x21a1989  [node]
[1]    132127 IOT instruction (core dumped)  node test.js
Additional information

Bug found during the investigation on https://github.com/bytecodealliance/endive/issues/102

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

使用 exhaust.wat、wasm-tools parse 和 test.js 重现该故障,然后检查报告中所示的 V8 堆和 OOM 堆栈附近的 WasmGC 分配路径。跟踪分配失败如何报告给 Node.js,并验证重现过程以可捕获的错误或 trap 结束,而不是中止进程。

由索引模型根据 Issue 内容生成。

评估

技术栈
javascript, nodejs, wasm
领域
backend, devtools
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
冷清
描述清晰度
基本清楚
新手友好度
45/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。