-
Notifications
You must be signed in to change notification settings - Fork 29.7k
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
lib: fix process.send() sync i/o regression #774
Conversation
The CI run seems to be conflicting with an already running one. I'll resubmit it in a bit. |
Running those changes on my 10.9.5 mac laptop:
I get tons of failed tests for some reason, all with either TIMEDOUT errors or with ENOSYS such as the following. While trying the use case as given in #760, I get the following error (much alike the test failing errors):
|
@brendanashworth are you sure you have the uv upgrade patch applied? |
@saghul oop, you're right, I needed to update my master before I branched to test this - my fault. On my system this now fixes it. <3 Besides the |
var proc = fork(__filename, ['child']); | ||
|
||
proc.on('message', common.mustCall(function(msg) { | ||
assert.equal(typeof(msg), 'string'); |
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.
is there a reason typeof(msg)
is used here instead of typeof msg
? I usually see the latter in the codebase
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.
No reason. In my head it's more of a function call than an operator. I'll drop the parens before I land it.
process.send() should be synchronous, i.e. it should block until the message has been sent in full, but it wasn't after the second-to-last libuv upgrade because of commit libuv/libuv@393c1c5 ("unix: set non-block mode in uv_{pipe,tcp,udp}_open"), which made its way into io.js in commit 07bd05b ("deps: update libuv to 1.2.1"). Commit libuv/libuv@b36d4ff ("unix: implement uv_stream_set_blocking()") as landed in io.js in commit 9681fca ("deps: update libuv to 1.4.0") makes it possible to restore the synchronous behavior again and that's precisely what this commit does. PR-URL: nodejs/node#774 Reviewed-by: Trevor Norris <[email protected]>
process.send() should be synchronous, it should block until the message has been sent in full, but it wasn't after the second-to-last libuv upgrade because of commit libuv/libuv@393c1c5 ("unix: set non-block mode in uv_{pipe,tcp,udp}_open"), which made its way into io.js in commit 07bd05b ("deps: update libuv to 1.2.1"). Commit libuv/libuv@b36d4ff ("unix: implement uv_stream_set_blocking()") as landed in io.js in commit 9681fca ("deps: update libuv to 1.4.0") makes it possible to restore the synchronous behavior again and that's precisely what this commit does. The same line of reasoning applies to `net.Socket({ fd: 1 })`: creating a socket object from a stdio file descriptor, like the `process.stdout` getter does, should put the file descriptor in blocking mode for compatibility reasons. Fixes: nodejs#760 Fixes: nodejs#784
f366417
to
1fea458
Compare
Updated with the feedback from #784. PTAL @brendanashworth @vkurchatkin. https://jenkins-iojs.nodesource.com/view/iojs/job/iojs+any-pr+multi/163/ |
LGTM |
@piscisaureus mentioned in passing something about blocking mode being unsafe on Windows but without going into details. I've asked him to chime in. |
I haven't run the tests but the code looks great to me. |
process.send() should be synchronous, it should block until the message has been sent in full, but it wasn't after the second-to-last libuv upgrade because of commit libuv/libuv@393c1c5 ("unix: set non-block mode in uv_{pipe,tcp,udp}_open"), which made its way into io.js in commit 07bd05b ("deps: update libuv to 1.2.1"). Commit libuv/libuv@b36d4ff ("unix: implement uv_stream_set_blocking()") as landed in io.js in commit 9681fca ("deps: update libuv to 1.4.0") makes it possible to restore the synchronous behavior again and that's precisely what this commit does. The same line of reasoning applies to `net.Socket({ fd: 1 })`: creating a socket object from a stdio file descriptor, like the `process.stdout` getter does, should put the file descriptor in blocking mode for compatibility reasons. PR-URL: nodejs/node#774 Reviewed-by: Trevor Norris <[email protected]>
On windows, process.send() has always been async. This bothers me and I wouldn't mind fixing it, but be aware that changing this now amounts to an API change. Doing synchronous writes to a pipe that's open in "overlapped" mode is currently not supported by libuv, we'd have to add support for it. |
@piscisaureus this is one of those areas where its not clear. this could be called a major revision/api change, or it could be called a bug that windows is not same as linux, and only a patch... It could also be considered a regression, because maybe unix should be async on process.send (and stdout/err), and this goes the other way. I don't have strong feelings. Its hard to know how many users depend on this sync feature on windows. I'd be tempted to call it a bug fix, for now, and make async on both in the next major (or streaming... but that's lots of work). |
process.send() should be synchronous, it should block until the message has been sent in full, but it wasn't after the second-to-last libuv upgrade because of commit libuv/libuv@393c1c5 ("unix: set non-block mode in uv_{pipe,tcp,udp}_open"), which made its way into io.js in commit 07bd05b ("deps: update libuv to 1.2.1"). Commit libuv/libuv@b36d4ff ("unix: implement uv_stream_set_blocking()") as landed in io.js in commit 9681fca ("deps: update libuv to 1.4.0") makes it possible to restore the synchronous behavior again and that's precisely what this commit does. The same line of reasoning applies to `net.Socket({ fd: 1 })`: creating a socket object from a stdio file descriptor, like the `process.stdout` getter does, should put the file descriptor in blocking mode for compatibility reasons. PR-URL: nodejs/node#774 Reviewed-by: Trevor Norris <[email protected]>
In the
With that, I'd say that Windows being async would be a bug and should be a patch. Plus, since |
Let's discuss at the next TC meeting.
That might be problematic, it sounds like it could break the child_process module. The libuv documentation for uv_pipe_open() doesn't mention that limitation, by the way. |
@brendanashworth the cluster docs you link to say |
process.send() should be synchronous, it should block until the message has been sent in full, but it wasn't after the second-to-last libuv upgrade because of commit libuv/libuv@393c1c5 ("unix: set non-block mode in uv_{pipe,tcp,udp}_open"), which made its way into io.js in commit 07bd05b ("deps: update libuv to 1.2.1"). Commit libuv/libuv@b36d4ff ("unix: implement uv_stream_set_blocking()") as landed in io.js in commit 9681fca ("deps: update libuv to 1.4.0") makes it possible to restore the synchronous behavior again and that's precisely what this commit does. The same line of reasoning applies to `net.Socket({ fd: 1 })`: creating a socket object from a stdio file descriptor, like the `process.stdout` getter does, should put the file descriptor in blocking mode for compatibility reasons. PR-URL: nodejs/node#774 Reviewed-by: Trevor Norris <[email protected]>
status? this is going back into "known issues" for 1.3.0 where we mentioned that a fix should "appear in the next patch release" (my words I think, sorry). |
If the send is synchronous, does that mean it also waits in the receiver to process the message or just the sending side blocks to perform the send to the kernel? |
The latter. There is no guarantee the receiver actually received it (or will receive it - the message is lost when the process goes away.) |
I did a simple merge of this and the latest master and ran a CI @ https://jenkins-iojs.nodesource.com/job/iojs+any-pr+multi/632/ on my branch and got a bunch of failures on windows:
/cc @piscisaureus |
This is going to slip for the 2.0 release as decided on the TC meeting on 4/29. Removing it from the milestone. |
@bnoordhuis will you have time to update this soon? |
I think I'd rather take a different approach and make the asynchronous nature of process.send() official. |
There will be a huge pain to my application if That being said, I suggest to let this method asynchronously by default .Synchronous message exchange should be applied via a flag or even another |
Just curious: how well it will perform while being async? Also, I think there are many userland modules, that are basically meant to do same thing as |
Performance-wise, it probably doesn't matter much if process.send() is synchronous or not; with most workloads, JSON.parse and JSON.stringify are the biggest cost centers. |
Closing, possibly to be rediscussed in #34 |
process.send() should be synchronous, i.e. it should block until the
message has been sent in full, but it wasn't after the second-to-last
libuv upgrade because of commit libuv/libuv@393c1c5 ("unix: set
non-block mode in uv_{pipe,tcp,udp}_open"), which made its way into
io.js in commit 07bd05b ("deps: update libuv to 1.2.1").
Commit libuv/libuv@b36d4ff ("unix: implement uv_stream_set_blocking()")
as landed in io.js in commit 9681fca ("deps: update libuv to 1.4.0")
makes it possible to restore the synchronous behavior again and that's
precisely what this commit does.
Fixes: #760
R=@brendanashworth @piscisaureus
On Windows, this sets the UV_HANDLE_BLOCKING_WRITES flag on the handle. I'd like @piscisaureus to confirm whether that's harmless or not.
https://jenkins-iojs.nodesource.com/view/iojs/job/iojs+any-pr+multi/160/