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

tty: implement ReadStream._final to avoid ENOTCONN on .end() #22900

Closed
wants to merge 1 commit into from

Conversation

mcollina
Copy link
Member

Fixes: #22814.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines

@nodejs-github-bot nodejs-github-bot added the tty Issues and PRs related to the tty subsystem. label Sep 17, 2018
@addaleax
Copy link
Member

Is this also a change that came with the libuv TTY changes?

My gut feeling would be that ignoring ENOTCONN during shutdown of any socket would also be a valid fix? Is there ever any benefit from reporting that error back to the user, if it happens while shutting down?

@mcollina
Copy link
Member Author

Is this also a change that came with the libuv TTY changes?

Yes.

My gut feeling would be that ignoring ENOTCONN during shutdown of any socket would also be a valid fix? Is there ever any benefit from reporting that error back to the user, if it happens while shutting down?

I think it's still valid for net.Socket. In this case it is happening because the writable side has never been opened, so it cannot really be shutdown (shutdown only works on writables).

@addaleax
Copy link
Member

I know why it’s being emitted… I guess my main issue with this approach is that it adds more special handling for different types of streams, when we’ve been putting some effort into reducing exactly that. Conceptually, the TTY code should not contain any stream specifics, imo…

Alternatively, would it make sense to skip the shutdownSocket call in net.js if stream.writable was false when the stream was created?

@mcollina
Copy link
Member Author

Alternatively, would it make sense to skip the shutdownSocket call in net.js if stream.writable was false when the stream was created?

I'll do that instead. It's more consistent.

@mcollina
Copy link
Member Author

I'm not super confident about this change. Specifically because process.stdin.write() would likely emit an ENOTCONN as well. I think we should error in that case. I'm not sure if we should skip it in this one as well because it is totally harmless. However, calling .end() on what is essentially a readable should not be ok according to the new libuv logic.

addaleax
addaleax previously approved these changes Sep 17, 2018
Copy link
Member

@addaleax addaleax left a comment

Choose a reason for hiding this comment

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

Thanks!

Specifically because process.stdin.write() would likely emit an ENOTCONN as well. I think we should error in that case.

I agree, silently swallowing input data is a different thing.

@mcollina
Copy link
Member Author

I'll see what process.stdin.write() does and open a PR in case.

@Fishrock123
Copy link
Contributor

CI seems to fail? I'm not sure about the exact specifics but it sounds reasonable.

@mcollina
Copy link
Member Author

@mcollina
Copy link
Member Author

@addaleax handling it within net is not working. I think we should go back to the _final override.

@@ -359,7 +364,7 @@ Socket.prototype._final = function(cb) {
debug('_final: not ended, call shutdown()');

// otherwise, just shutdown, or destroy() if not possible
if (!this._handle || !this._handle.shutdown) {
if (!this[kShouldShutdown] || !this._handle || !this._handle.shutdown) {
Copy link
Member

Choose a reason for hiding this comment

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

I think the issue might be that this runs destroy() when it previously didn’t.

I can try it too (later), but maybe undoing this line change and adding if (!this[kShouldShutdown]) return cb(); below works?

Copy link
Member Author

Choose a reason for hiding this comment

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

It doesn't because the writable: false parameter that is passed in to the net.Socket constructor does control other behaviors internally, and it does not mean "this is half-open".
If you want to give it a shot, feel free to push here. Otherwise we revert to the _final  solution.

@@ -66,6 +66,7 @@ function ReadStream(fd, options) {
}
inherits(ReadStream, net.Socket);


Copy link
Contributor

Choose a reason for hiding this comment

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

Unrelated change?

@@ -245,6 +246,10 @@ function Socket(options) {
options.writable = options.writable || false;
const { allowHalfOpen } = options;

// Needed to avoid to call uv_shutdown during _final
Copy link
Contributor

Choose a reason for hiding this comment

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

"to call" -> "calling"

@addaleax
Copy link
Member

I think libuv/libuv@4049879 may have fixed this as well, by making things work again on the libuv side?

@mcollina
Copy link
Member Author

I think so. Have you tested it?

@addaleax
Copy link
Member

@mcollina Just checked, and yes, it does fix ./node -e 'process.stdin.end();' when run on a TTY. 🎉

@addaleax addaleax dismissed their stale review September 19, 2018 16:36

Would prefer to wait for libuv patch (should be soon enough?)

@mcollina
Copy link
Member Author

Let's wait for that.

addaleax pushed a commit to addaleax/node that referenced this pull request Sep 24, 2018
@addaleax
Copy link
Member

I’ve opened a PR with only the test changes here (and attribution to you), so I hope it’s okay to close this. You know what to do if I’m mistaken :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tty Issues and PRs related to the tty subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants