nodejs / nodejs/node

fileHandle.readableWebStream sometimes crashes on large inputs

Đang mở
#56,116 8 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

confirmed-bug stream web streams
Ngôn ngữ chính
JavaScript
Star
122k
Fork
37.3k
Merge trung bình
4 ngày 2 giờ
Pull request đã merge (30 ngày)
283

Mô tả

Version

v22.10.0

Platform

Reproducible on:

Linux smooreswork 6.11.8-300.fc41.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Nov 14 20:37:39 UTC 2024 x86_64 GNU/Linux

Linux 04d2433b1ce0 6.1.49-Unraid #1 SMP PREEMPT_DYNAMIC Wed Aug 30 09:42:35 PDT 2023 x86_64 x86_64 x86_64 GNU/Linux

Linux server 6.8.0-49-generic #49-Ubuntu SMP PREEMPT_DYNAMIC Mon Nov  4 02:06:24 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
Subsystem

fs/promises

What steps will reproduce the bug?
import { open } from "node:fs/promises"

/**
 * Like readFile, but streams the file into memory in chunks
 * to avoid hard-coded 2GB limit on file I/O operations in
 * Node.js/libuv https://github.com/libuv/libuv/pull/1501
 *
 * @param {string} path
 * @returns {Promise<Uint8Array>}
 */
export async function streamFile(path) {
  const fileHandle = await open(path)
  try {
    const stats = await fileHandle.stat()
    const fileData = new Uint8Array(stats.size)
    let i = 0
    for await (const chunk of fileHandle.readableWebStream()) {
      const chunkArray = new Uint8Array(chunk)
      fileData.set(chunkArray, i)
      i += chunkArray.byteLength
    }
    return fileData
  } finally {
    await fileHandle.close()
  }
}

Run the above function on any relatively large file in the Node.js REPL. The larger the file, the more consistent the failure. With a ~100MB file, I get the error maybe 1 in every 20 attempts on my laptop. With a 600MB file, it's more like every other attempt.

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

The file must be sufficiently large. I have never seen this occur with files smaller than 50MB. With files less than 200MB, it occurs occasionally. With files larger than 500MB, it occurs very consistently.

I attempted to reproduce this in a simple node.js ESM script, but it does not seem to reproduce when the above function is run in a script. I can reproduce consistently in the REPL, and this same issue occurs consistently in the Storyteller Next.js app, where that code sample is from.

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

The streamFile function should successfully read files of any length into memory. It reads files one chunk at a time to avoid libuv's hard limit on 2GB file I/O operations. There should be no crash or warning about closing a file descriptor on garbage collection, because the file descriptor is closed in a finally block.

What do you see instead?
> await streamFile('./large-test-file.m4b')
(node:460551) Warning: Closing file descriptor 42 on garbage collection
(node:460551) [DEP0137] DeprecationWarning: Closing a FileHandle object on garbage collection is deprecated. Please close FileHandle objects explicitly using FileHandle.prototype.close(). In the future, an error will be thrown if a file descriptor is closed during garbage collection.

After this error log, the Node REPL itself exits with status code 139

Additional information

If I swap fileHandle.readableWebStream() out for fileHandle.createReadStream(), this works without issue for files of any size.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. 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.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu tại điểm vào fs/promises FileHandle.prototype.readableWebStream() và tái hiện sự cố trong Node.js REPL bằng hàm streamFile được cung cấp và một tệp lớn. So sánh hành vi với fileHandle.createReadStream(). Được xem là hoàn tất khi các lần đọc lớn hoàn thành mà không bị crash, không có cảnh báo garbage collection của bộ mô tả tệp và không khiến REPL thoát ngoài dự kiến.

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, operating-systems
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
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
35/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.