Skip to content

fs: move FileHandle close on GC to EOL #58536

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

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

jasnell
Copy link
Member

@jasnell jasnell commented May 31, 2025

Automatically closing a FileHandle on garbage collection has been deprecated for some time now. We've said that it will eventually be removed and become and error.

This PR also adds a new autoClose option to the FileHandle readableWebStream() API in order to deal with a possible bug in which the readable stream that wraps the FileHandle is passed out of a context where the FileHandle is accessible to be closed.

Automatically closing a FileHandle on garbage collection
has been deprecated for some time now. We've said that
it will eventually be removed and become and error.
@jasnell jasnell added fs Issues and PRs related to the fs subsystem / file system. semver-major PRs that contain breaking changes and should be released in the next major version. deprecations Issues and PRs related to deprecations. labels May 31, 2025
@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. labels May 31, 2025
Copy link

codecov bot commented May 31, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 90.25%. Comparing base (968e2f4) to head (f8e6d89).
Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #58536      +/-   ##
==========================================
+ Coverage   90.21%   90.25%   +0.03%     
==========================================
  Files         635      635              
  Lines      187580   187575       -5     
  Branches    36853    36859       +6     
==========================================
+ Hits       169231   169290      +59     
+ Misses      11108    11055      -53     
+ Partials     7241     7230      -11     
Files with missing lines Coverage Δ
lib/internal/fs/promises.js 98.32% <100.00%> (+0.01%) ⬆️
src/env-inl.h 93.34% <ø> (-0.08%) ⬇️
src/env.h 98.14% <ø> (ø)
src/node_file.cc 75.91% <100.00%> (-0.17%) ⬇️

... and 33 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@LiviaMedeiros
Copy link
Member

This PR also adds a new autoClose option to the FileHandle readableWebStream() API in order to deal with a possible bug in which the readable stream that wraps the FileHandle is passed out of a context where the FileHandle is accessible to be closed.

Unless there already is a trivial userspace solution to this or autoClose defaults to true, I think we should land the new option first and wait some extra time before making this EOL (assuming greenish enough CITGM).

@LiviaMedeiros LiviaMedeiros added the needs-citgm PRs that need a CITGM CI run. label May 31, 2025
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@nodejs-github-bot
Copy link
Collaborator

@jasnell jasnell added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Jun 1, 2025
Copy link
Member

@LiviaMedeiros LiviaMedeiros left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I have to be more explicit here.
I don't think we should land a breaking change at the same time as the feature that allows to avoid breakage in userland.
The autoClose option must be a separate, backportable, semver-minor PRs that contain new features and should be released in the next minor version. PR, and it must be accessible to users before DEP0137 goes EOL. I think it's still fine to make it EOL in v25.x, as long as users have a few months to use autoClose.

Also I think that in the semver-major PRs that contain breaking changes and should be released in the next major version. PR autoClose should become true by default, to align with filehandle.createReadStream()/filehandle.createWriteStream()/etc. and to minimize breakage.


There are a few test failures.
fs-read-offset-null and fs-read-empty-buffer look trivial to fix (#58543)
The FATAL ERROR: v8::HandleScope::CreateHandle() Cannot create a handle without a HandleScope in https://ci.nodejs.org/job/node-test-commit-arm-debug/18769/ also might be related.

Comment on lines +50 to +55
try {
const hostname = await fileHandle.readFile();
assert.ok(hostname.length > 0);
} finally {
await fileHandle.close();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: since this is part of semver-major change, we can use ERM right away.

Suggested change
try {
const hostname = await fileHandle.readFile();
assert.ok(hostname.length > 0);
} finally {
await fileHandle.close();
}
{
await using fileHandle = await open('/proc/sys/kernel/hostname', 'r');
const hostname = await fileHandle.readFile();
assert.ok(hostname.length > 0);
}

const ondone = FunctionPrototypeBind(this[kUnref], this);
const ondone = async () => {
this[kUnref]();
if (options.autoClose) this.close();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we await here?

Suggested change
if (options.autoClose) this.close();
if (options.autoClose) await this.close();

// throwing the error until the next immediate queue tick so as not
// to interfer with the gc process.
env()->SetImmediate([](Environment* env) {
THROW_ERR_INVALID_STATE(env,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lint

Suggested change
THROW_ERR_INVALID_STATE(env,
THROW_ERR_INVALID_STATE(
env,

@LiviaMedeiros LiviaMedeiros removed the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Jun 1, 2025
@jasnell jasnell marked this pull request as draft June 1, 2025 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. deprecations Issues and PRs related to deprecations. fs Issues and PRs related to the fs subsystem / file system. lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. needs-citgm PRs that need a CITGM CI run. semver-major PRs that contain breaking changes and should be released in the next major version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants