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

[Bugfix] Ensure writable streams are ended on PTY close #59

Merged
merged 22 commits into from
Mar 12, 2025

Conversation

daweifeng-replit
Copy link
Contributor

What is this PR?

The writable stream in PTY is never set to 'unwritable' when PTY is closed or when the child process dies.

Changes

  • Add this.#writable.end() in close() and exit() methods of Pty class
  • Update tests to verify write and read streams are no longer writable/readable after PTY closes

Copy link
Member

@szymonkaliski szymonkaliski left a comment

Choose a reason for hiding this comment

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

this looks good to me, though I don't know if there aren't any intricacies downstream from this, so would love @jackyzha0 / @lhchavez to have a look too

@@ -141,6 +142,7 @@ export class Pty {
// end instead of destroy so that the user can read the last bits of data
// and allow graceful close event to mark the fd as ended
this.#socket.end();
this.#writable.end();
Copy link
Contributor

Choose a reason for hiding this comment

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

why do we need to do this proactively instead of waiting for handleClose to be called?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is to prevent a race condition that there is a time window after close() is called and before handleClose() is called and during this time the underlaying socket might be closed, if it tries to write to the socket, it will fail to write. So I think it might make sense to synchronize the state of both streams? 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

gotcha, that makes sense. but now we are opening ourselves for a double-close bug if the closed message is delivered after an explicit call to close(). is it totally safe to close the writable twice? if it's not, should we add one more flag to ensure that we close it at most once?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes! It is idempotent. You can see that in the Writable source code below.

https://github.com/nodejs/node/blob/365faa7a4fbf973741600990b606d848ce0dcc14/lib/internal/streams/writable.js#L836

@daweifeng-replit daweifeng-replit merged commit 9e82206 into main Mar 12, 2025
6 checks passed
@daweifeng-replit daweifeng-replit deleted the dawei/end-writable-on-close branch March 12, 2025 19:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants