Skip to content

child_process: add callback parameter to .send()#2620

Closed
bnoordhuis wants to merge 1 commit into
nodejs:masterfrom
bnoordhuis:fix-760
Closed

child_process: add callback parameter to .send()#2620
bnoordhuis wants to merge 1 commit into
nodejs:masterfrom
bnoordhuis:fix-760

Conversation

@bnoordhuis

Copy link
Copy Markdown
Member

Add an optional callback parameter to ChildProcess.prototype.send()
that is invoked when the message has been sent.

Juggle the control channel's reference count so that in-flight messages
keep the event loop (and therefore the process) alive until they have
been sent.

ChildProcess.prototype.send() and process.send() used to operate
synchronously but became asynchronous in commit libuv/libuv@393c1c5
("unix: set non-block mode in uv_{pipe,tcp,udp}_open"), which landed
in io.js in commit 07bd05b ("deps: update libuv to 1.2.1").

Fixes: #760

R=@rvagg - note that I'm on holiday and may not be able to respond quickly if at all.

CI: https://jenkins-iojs.nodesource.com/job/node-test-pull-request/211/

@mscdex mscdex added the child_process Issues and PRs related to the child_process subsystem. label Aug 30, 2015
@rvagg

rvagg commented Aug 30, 2015

Copy link
Copy Markdown
Member

Looks great to me, two concerns: 1) the FIXME and 2) the ref/unref timing and potential for it to go below zero, obviously it shouldn't and I'm not suggesting your code has a way to do this but in the interests of defensiveness I wonder if the decrement shouldn't have a guard for < 0 because the ref is strictly when it reaches 1.

I'm happy with this going into v4, the doc changes are appreciated too. I'm also impressed this actually works on Windows! Some kind of black magic.

@Fishrock123

Copy link
Copy Markdown
Contributor

@bnoordhuis how does this interact with windows, where afaik you don't get this return info?

@Fishrock123 Fishrock123 added this to the 4.0.0 milestone Aug 30, 2015
@Fishrock123 Fishrock123 added the semver-major PRs that contain breaking changes and should be released in the next major version. label Aug 30, 2015
Comment thread doc/api/child_process.markdown Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

While here mind fixing placement of the first [?

@ronkorving

Copy link
Copy Markdown
Contributor

Known issues in each changelog says:

process.send() is not synchronous as the docs suggest, a regression introduced in 1.0.2, see #760.

Does this mean that the intention is to keep it asynchronous? (in which case it's no longer a known issue, but rather BC breakage)

@rvagg

rvagg commented Aug 31, 2015

Copy link
Copy Markdown
Member

yes and yes

@ronkorving

Copy link
Copy Markdown
Contributor

Thanks 👍

Comment thread lib/internal/child_process.js Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Any reason not to just nextTick() this right now?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

None that I can think of but it wouldn't be the first time a seemingly innocuous looking change breaks something. If we can get consensus, I'll change it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

After looking through the code base, there are actually many places where errors are emitted on the same tick. Maybe the FIXME should just be removed instead.

@bnoordhuis

Copy link
Copy Markdown
Member Author

the ref/unref timing and potential for it to go below zero

That would be a logic error. I can add an assert if you want.

Incorporated @trevnorris's suggestions, PTAL (and good one on the process.nextTick() overload, I forgot that existed.)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This impacts the cluster API and process API, which surface .send().

I assume process will now have an error event which can be emitted if send fails, and node will crash if it isn't listened on?

For users of cluster, if they fail to listen on worker.process.on('error', ..., the master will crash? Or will you re-emit from the process object onto the worker object?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

There is no change in functionality - what's described here is the the current behavior, it just wasn't documented.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I thought send() after disconnect resulted in an error being thrown, not an error emitted, currently.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It emits an error event, but a synchronous one. So yes, if you don't have an error listener, it's effectively throwing an exception. That behavior is (for better or worse) maintained in this patch.

@trevnorris

Copy link
Copy Markdown
Contributor

Nothing else from me. LGTM.

Add an optional callback parameter to `ChildProcess.prototype.send()`
that is invoked when the message has been sent.

Juggle the control channel's reference count so that in-flight messages
keep the event loop (and therefore the process) alive until they have
been sent.

`ChildProcess.prototype.send()` and `process.send()` used to operate
synchronously but became asynchronous in commit libuv/libuv@393c1c5
("unix: set non-block mode in uv_{pipe,tcp,udp}_open"), which landed
in io.js in commit 07bd05b ("deps: update libuv to 1.2.1").
@bnoordhuis

Copy link
Copy Markdown
Member Author

@Fishrock123

Copy link
Copy Markdown
Contributor

https://ci.nodejs.org/job/node-test-commit-arm/434/nodes=armv7-wheezy/tapTestReport/

not ok 838 - eval_messages.js
# [eval]
# [eval]:1
# with(this){__filename}
# ^^^^
# 
# SyntaxError: Strict mode code may not include a with statement
# at Object.exports.runInThisContext (vm.js:53:16)
# at Object.<anonymous> ([eval]-wrapper:6:22)
# at Module._compile (module.js:430:26)
# at node.js:566:27
# at doNTCallback0 (node.js:407:9)
# at process._tickCallback (node.js:336:13)
# 42
# 42

How the hell is that failing here all of a sudden??

@rvagg

rvagg commented Sep 2, 2015

Copy link
Copy Markdown
Member

that output is normal output for eval_messages.js and doesn't necessarily indicate why it's failing, something else is going on to make it fail and the output isn't being very helpful

@trevnorris

Copy link
Copy Markdown
Contributor

Can we just try CI again to see if we get lucky and it passes? Would be nice to get this landed.

@orangemocha

Copy link
Copy Markdown
Contributor

Could the failure be related to this PR, or is that test just flaky?

@trevnorris

Copy link
Copy Markdown
Contributor

@orangemocha Believe it's just a flaky test.

@orangemocha

Copy link
Copy Markdown
Contributor

Okay, I opened #2648 to mark it so.

@jasnell

jasnell commented Sep 2, 2015

Copy link
Copy Markdown
Member

Overall the change LGTM. Where are things at with regards to the failing CI? Were the failures unrelated?

@trevnorris

Copy link
Copy Markdown
Contributor

bnoordhuis added a commit that referenced this pull request Sep 3, 2015
Add an optional callback parameter to `ChildProcess.prototype.send()`
that is invoked when the message has been sent.

Juggle the control channel's reference count so that in-flight messages
keep the event loop (and therefore the process) alive until they have
been sent.

`ChildProcess.prototype.send()` and `process.send()` used to operate
synchronously but became asynchronous in commit libuv/libuv@393c1c5
("unix: set non-block mode in uv_{pipe,tcp,udp}_open"), which landed
in io.js in commit 07bd05b ("deps: update libuv to 1.2.1").

Fixes: #760
PR-URL: #2620
Reviewed-By: trevnorris - Trevor Norris <trev.norris@gmail.com>
Reviewed-By: jasnell - James M Snell <jasnell@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

child_process Issues and PRs related to the child_process subsystem. semver-major PRs that contain breaking changes and should be released in the next major version.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants