-
Notifications
You must be signed in to change notification settings - Fork 29.9k
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
net: do not inherit the no-half-open enforcer #18974
Conversation
Ping @nodejs/collaborators. |
lib/net.js
Outdated
// There is already a "no-half-open enforcer" in place so there is no need to | ||
// inherit it again from `Duplex`. | ||
stream.Readable.call(this, options); | ||
stream.Writable.call(this, options); |
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 am not really a fan of this … not calling the Duplex
constructor seems like a bad idea in general, and it’s going to be an extra obstacle while working on merging all StreamBase
JS wrappers…
Can we instead make the Duplex
constructor not attach the event handler if options.allowHalfOpen
is set? That would help all other Duplex streams as well…
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.
Yes, after #18953 my idea was to override the allowHalfOpen
option when calling the Duplex
constructor in order to never inherit the listener but to do that the options object has to be copied. This was done for performance reasons.
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'm open to suggestions.
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.
@lpinca Yeah, good point.
I don’t think we can get around that without making some kind of change to the Duplex
API, but I would be okay with that.
The best I can come up with right now would be this:
- Add
Duplex.kHasHalfOpenEnforcer = Symbol('kHasHalfOpenEnforcer'); // or non-enumerable Duplex.prototype[Duplex.kHasHalfOpenEnforcer] = true; net.Socket.prototype[Duplex.kHasHalfOpenEnforcer] = false;
- Check for that property in the
Duplex
constructor
Another approach might be to create an internal Duplex
constructor that omits the listener addition, which could serve as a base class of the “real”, publicly exposed Duplex
stream…
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'm not very happy with option 1, adapting the base class to the needs of the child seems kinda hackish. Will think a bit about the second approach.
@@ -267,7 +276,7 @@ function Socket(options) { | |||
this._writableState.decodeStrings = false; | |||
|
|||
// default to *not* allowing half open sockets | |||
this.allowHalfOpen = options && options.allowHalfOpen || false; | |||
this.allowHalfOpen = options.allowHalfOpen || false; |
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.
… and, as I understand it, would allow us to get rid of this, if we just transform allowHalfOpen
correctly to begin with?
Also, I don’t know what the motivation for this was, but I don’t get why the default is not allowing half-open connections.
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.
This is unrelated but options
is always an object so there is no reason to see if it's truthy.
I'm fine with either the solution here or the one addaleax suggested. |
1d5513d
to
a1c475d
Compare
@addaleax @benjamingr PTAL when you have some time. I will reorganize commits if this is acceptable. New CI: https://ci.nodejs.org/job/node-test-pull-request/13500/ |
I'm -1 on the overall approach. Why cannot it be implemented only in If we go with this approach, we must move all the defined properties from This goes against the generic intent of reducing how we rely on streams internals. |
@mcollina read discussion in #18974 (comment)
To do that we can set the Workarounds:
As said I'm open to suggestions. |
@lpinca Matteo has a point … what’s the downside of removing the extra code in |
That means doing the work twice, no? First to add the listener in the |
@lpinca If we want to use the |
Assume that we instantiate the const socket = new Socket({ allowHalfOpen: false }); The |
Removing the
|
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.
Still LGTM and nicer now.
The I'd be actually 👍 in improving the |
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.
Making my -1 explicit and flagging it at as semvermajor, because socket instanceof Duplex
would now return false
.
@mcollina That’s incorrect, it does return |
lib/net.js
Outdated
@@ -223,7 +224,9 @@ function Socket(options) { | |||
else if (options === undefined) | |||
options = {}; | |||
|
|||
stream.Duplex.call(this, options); | |||
// There is already a "no-half-open enforcer" in place so there is no need to | |||
// inherit it again from `Duplex`. |
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.
Can you please add a note along the following lines: Socket is still inheriting from Duplex, but we are just using a slimmed down constructor. socket instanceOf Duplex would keep returning true
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.
Will do.
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.
@mcollina updated, PTAL.
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.
LGTM with a nit.
a1c475d
to
a40a803
Compare
a40a803
to
e530c3f
Compare
Add ability to subclass `stream.Duplex` without inheriting the "no-half-open enforcer" regardless of the value of the `allowHalfOpen` option.
`Socket.prototype.destroySoon()` is called as soon as `UV_EOF` is read if the `allowHalfOpen` option is disabled. This already works as a "no-half-open enforcer" so there is no need to inherit another from `stream.Duplex`.
e530c3f
to
5b73a79
Compare
Rebased and added a new test. |
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.
LGTM
Add ability to subclass `stream.Duplex` without inheriting the "no-half-open enforcer" regardless of the value of the `allowHalfOpen` option. PR-URL: #18974 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Chen Gang <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
`Socket.prototype.destroySoon()` is called as soon as `UV_EOF` is read if the `allowHalfOpen` option is disabled. This already works as a "no-half-open enforcer" so there is no need to inherit another from `stream.Duplex`. PR-URL: #18974 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Chen Gang <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Landed in 42e9b48...4e86f9b. |
Add ability to subclass `stream.Duplex` without inheriting the "no-half-open enforcer" regardless of the value of the `allowHalfOpen` option. PR-URL: #18974 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Chen Gang <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
`Socket.prototype.destroySoon()` is called as soon as `UV_EOF` is read if the `allowHalfOpen` option is disabled. This already works as a "no-half-open enforcer" so there is no need to inherit another from `stream.Duplex`. PR-URL: #18974 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Chen Gang <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Add ability to subclass `stream.Duplex` without inheriting the "no-half-open enforcer" regardless of the value of the `allowHalfOpen` option. PR-URL: #18974 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Chen Gang <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
`Socket.prototype.destroySoon()` is called as soon as `UV_EOF` is read if the `allowHalfOpen` option is disabled. This already works as a "no-half-open enforcer" so there is no need to inherit another from `stream.Duplex`. PR-URL: #18974 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Chen Gang <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Add ability to subclass `stream.Duplex` without inheriting the "no-half-open enforcer" regardless of the value of the `allowHalfOpen` option. PR-URL: nodejs#18974 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Chen Gang <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
`Socket.prototype.destroySoon()` is called as soon as `UV_EOF` is read if the `allowHalfOpen` option is disabled. This already works as a "no-half-open enforcer" so there is no need to inherit another from `stream.Duplex`. PR-URL: nodejs#18974 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Chen Gang <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Should this be backported to 8.x? If so, a separate backport PR is needed |
Socket.prototype.destroySoon()
is called as soon asUV_EOF
is readif the
allowHalfOpen
option is disabled. This already works as a"no-half-open enforcer" so there is no need to inherit another from
stream.Duplex
.Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
net