Skip to content
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

fs: allow FileHandle to outlive ReadableStream #45917

Closed
wants to merge 3 commits into from

Conversation

Slayer95
Copy link

Quoting @wolfgang42 at #45721 :

there's no way to only partially consume an fs.ReadStream created from a file handle without either closing the handle or leaking the stream.

@nodejs-github-bot nodejs-github-bot added fs Issues and PRs related to the fs subsystem / file system. needs-ci PRs that need a full CI run. labels Dec 20, 2022
Slayer95 referenced this pull request Dec 20, 2022
Support creating a Read/WriteStream from a
FileHandle instead of a raw file descriptor
Add an EventEmitter to FileHandle with a single
'close' event.

Fixes: #35240

PR-URL: #35922
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Rich Trott <rtrott@gmail.com>
@ronag
Copy link
Member

ronag commented Dec 20, 2022

I think #45909 is a better solution and doesn't involve weak refs.

@Slayer95
Copy link
Author

As far as I can tell, #45909 fixes an event handler leak for streams that do get destroyed. In contrast, this PR fixes non-destroying iterators. So, in order not to leave loose ends in resource management. they are complementary rather than competing approaches.

@ronag
Copy link
Member

ronag commented Dec 20, 2022

Not destroying a stream is a bug though. So this is basically a way to make those bugs less severe/observable?

@Slayer95
Copy link
Author

Not destroying a stream is a bug though

As per #38526, it looks like a feature to me. One may think that reusing a file handle after a stream reads from it should be supported, and that said stream should not be kept in memory. Am I missing something?

@ronag
Copy link
Member

ronag commented Dec 20, 2022

Streams should always be destroyed.

@ronag
Copy link
Member

ronag commented Dec 20, 2022

Destroying the stream just unrefs the handle. If there are other refs they are still usable.

@Slayer95
Copy link
Author

Gotcha. Therefore, the issue of the file handle unexpectedly dying at #45721 arises because the file handle is left without refs to it. According to my reading, that's documented behavior, although somewhat controversial (is there currently a way to opt out of it in a per-handle basis?). Thanks for the pointers, @ronag .

Ok, so changing up the context. Suppose there is an HTTP server implemented using Node.js' FileHandle. A malicious agent requests some file very slowly to it. Simultaneously, there is normal traffic requesting the same file. If the server uses a single shared file handle for all those requests, then the close event of the file handle may be boundlessly delayed by the malicious request. Before it's emitted, all the requests streams will remain referred to by the file handle, eventually resulting in DoS. Unless... those streams can be GCed before the FileHandle emits close.

@wolfgang42
Copy link

In contrast, this PR fixes non-destroying iterators.

Streams should always be destroyed.

I think, unless I’m missing something, I do want to be destroying my streams (as @ronag says this is mandatory, which seems sensible); I just don’t want that to close the underlying file handle.

Destroying the stream just unrefs the handle. If there are other refs they are still usable.

As @Slayer95 noted in #45721 (comment), this doesn't seem to be true:

The docs also state that destroying the stream closes internal resources, which may only be understood as releasing the fd, and that's in fact all it does.

Therefore, the issue of the file handle unexpectedly dying at #45721 arises because the file handle is left without refs to it.

Unless I’ve misunderstood what you mean by either “handle” or “refs”, this is not true: in our examples, fh.fd gets printed after the handle is closed (resulting in -1), so we're obviously retaining a reference to fh to make that possible.

...malicious agent requests some file very slowly to it...

Worth noting that, if I’ve understood your scenario correctly, there doesn’t even need to be anything malicious for this to be a problem: I’m intending to keep this FileHandle open for potentially days at a time anyway, so I definitely need the streams to go away when I’m done with them. (I can’t just reopen the file by path because I’m relying on POSIX filesystem semantics for atomic updates, so someone might have replaced the file out from under me in the meantime and I still need the old data until I’m ready to swap.)

@Slayer95
Copy link
Author

Slayer95 commented Dec 25, 2022

After testing the updated #45909 and a floating patch for proper access to [kFd], that approach looks sound and it fixes all concerns I have, so I'll close this PR in favor of yours, @ronag .

@Slayer95 Slayer95 closed this Dec 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fs Issues and PRs related to the fs subsystem / file system. needs-ci PRs that need a full CI run.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants