-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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: make readable/writable start as true #32272
Conversation
64e26b8
to
33f143b
Compare
`net.Socket` is slightly breaking stream invariants by having readable/writable going from `false` to `true`. Streams assume that readable/writable starts out `true` and then goes to `false` through `push(null)`/`end()` after which it never goes back to `true`, e.g. once a stream is `writable == false` it is assumed it will never become `true`. This PR changes 2 things: Unless explicitly set to `false` through options: - starts as `readable`/`writable` `true` by default. - uses `push(null)`/`end()` to set `readable`/`writable` to `false`. Note that this would cause the socket to emit the `'end'`/`'finish'` events, which it did not do previously. In the case it is explicitly set to `false` through `options` it is assumed to never become `true`.
33f143b
to
ba32528
Compare
// The readable flag is only needed if pauseOnCreate will be handled. | ||
readable: tlsOptions.pauseOnConnect, | ||
writable: false | ||
manualStart: 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.
What we actually want here is manualStart
since we in the lines below actually do manually start it.
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.
process.nextTick(initRead, this, socket);
https://github.com/nodejs/node/pull/32272/files#diff-04c3a6bcf355f2e05e7700c1b253d475L518
So a key challenge here is that Streams have never really had a clearly defined semantic around "I'm writable/readable yes, but you can't write or read yet". With both http/2 and quic we've essentially had to hack our way around this by deferring write and read operations until a "ready" event occurs, which is rather messy. What would be ideal here is some kind of proper, performant notion of a ready status that allows writes to be internally buffered prior to the ready state, then passed through like normal after the ready state... that would allow us to avoid the deferral hacks and cork/uncork dance while we're waiting for the underlying socket and communication sessions to be established. |
In other words, I'd prefer to have the underlying mechanism in stream.Writable, stream.Readable, and stream.Duplex addressed first then have these specific implementations build on that. |
I totally agree we need something like that. But I'm unsure whether that should block this? We have a way that it "works" today, shouldn't we make it consistent first? It might take quite a while until we have such a mechanism you suggest. |
I'm not sure really. I really dislike the hacks we have in place now ;-) .... I won't block this PR waiting for the other mechanism but would definitely like to see work on the other progress. |
I agree, my point here though is to try and reduce the hacks... a little bit...
Definitely something I would like to look into in the future. |
if this gets merged I think we could eventually deprecate |
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, just 2 nits.
It needs a close look of CITGM
@mcollina Added comments, 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
CITGM looks good |
needs another @nodejs/tsc approval |
Landed in eeccd52 |
`net.Socket` is slightly breaking stream invariants by having readable/writable going from `false` to `true`. Streams assume that readable/writable starts out `true` and then goes to `false` through `push(null)`/`end()` after which it never goes back to `true`, e.g. once a stream is `writable == false` it is assumed it will never become `true`. This PR changes 2 things: Unless explicitly set to `false` through options: - starts as `readable`/`writable` `true` by default. - uses `push(null)`/`end()` to set `readable`/`writable` to `false`. Note that this would cause the socket to emit the `'end'`/`'finish'` events, which it did not do previously. In the case it is explicitly set to `false` through options` it is assumed to never become `true`. PR-URL: #32272 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]>
If the socket is writable, a write is attempted and an `ERR_SOCKET_CLOSED` error is emitted because the socket was never connected. Refs: nodejs/node#32272
If the socket is writable, a write is attempted and an `ERR_SOCKET_CLOSED` error is emitted because the socket was never connected. Refs: nodejs/node#32272
If the socket is writable, a write is attempted and an `ERR_SOCKET_CLOSED` error is emitted because the socket was never connected. Refs: nodejs/node#32272
net.Socket
is slightly breaking stream invariants by having readable/writable going fromfalse
totrue
.Streams assume that readable/writable either starts out as
false
and stay that way, ortrue
and then goes tofalse
throughpush(null)
/end()
after which it never goes back totrue
.This PR changes 2 things:
Unless explicitly set to
false
through options:readable
/writable
true
by default.net.Socket
does not manage/setreadable/writable
, that's internal/privatestream state.
push(null)
/end()
to setreadable
/writable
tofalse
if required after connect. Note that this would cause the socket to emit the'end'
/'finish'
events, which it did not do previously.In the case it is explicitly set to
false
throughoptions
it never becomestrue
.Currently something like this would fail:
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes