-
Notifications
You must be signed in to change notification settings - Fork 288
Handle writes to non-blocking pty instead of wrapping via Node's tty api #831
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
Merged
Merged
Changes from 2 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
3bc1409
Speculative fix for stream backpressure
Tyriar bb8a1af
Add additional change needed to fix it
Tyriar b8ecd5e
Use raw write stream, handle partial writes/kernel backpressure
Tyriar 8b2b77b
Remove unneeded write stream
Tyriar 3538d16
Remove unwanted logs
Tyriar 80b2af7
Tidy up comments
Tyriar 872ff8e
Add setting of encoding on the read socket back
Tyriar 1674fdf
Move props to top
Tyriar 6bb38cc
Use os.constants.errno
Tyriar c6b06ed
Revert "Use os.constants.errno"
Tyriar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest the original approach of one stream because:
fs.writemay not write all the data passed to it because the underlying system call doesn't guarantee all bytes are written. To usefs.writehere, it would need to do something likedata = data.slice(Buffer.byteLength(data) - written)and write again until data.length is emptyfs.writeenqueues it to a threadpool (or io_uring) which means multiple write() calls could happen at the same time and in an interleaving order. To use fs.write here, this function would need to enqueue each write call and drain one after anotherI think the question is why did it stop writing the final chunk? If I was debugging this, I would try to reproduce it and then run either
strace node <file>orperf trace node <file>and compare the logs in the success scenario versus the failure scenario. Is it missing a write at the end? Did the write happen after the process already exited?Since this native module is handling process spawning, I would also closely compare the libuv implementation of process spawning with this one.
My suspicion is that this is an edgecase in node:stream where when one end of the socket is shutdown, it caused the other end to stop sending data (sort of like
allowHalfOpen)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't actually see this until just now after pushing. It's hinted to in the code, but note also there's a hang issue when writing on macOS specifically that can occur that is closely related to all this stuff (microsoft/vscode#246204).
I have a better implementation now that's pretty close to what you were suggesting. It's using
fs.writedirectly and handles partial writes andEAGAIN. Here are some details I found which made it particularly confusing to work through:fs.WriteStreamreturnsERR_SYSTEM_ERRORwhich obfuscated the actual underlyingEAGAINso I couldn't handle it,fs.writewas needed for this.drainevent never seems to happen fortty.WriteStream, it's implemented inWritablebut nottty.WriteStream. I couldn't find why though, this is what an LLM said:tty.WriteStreamhas a habit of locking up the process completely when callingwritewith too much data. @lhecker investigated the hang earlier today and found it would always get stuck inuv__writeRemove ugly throttling mechanism when pasting to the terminal vscode#283056 (comment). Decided not to investigate further and usefs.writeas it appears simpler and seems to accomplish the goals.