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

child_process: exec's promisify impl now includes stdout/err in error #13388

Closed
wants to merge 4 commits into from
Closed

child_process: exec's promisify impl now includes stdout/err in error #13388

wants to merge 4 commits into from

Conversation

giltayar
Copy link
Contributor

@giltayar giltayar commented Jun 2, 2017

This converts the initial implementation of a promised exec that used
the customPromisifyArgs support in util.promisify with a custom
implementation. This is because exec and execFile, when there is an
error, still supply the stdout and stderr of the process, and yet
the promisified version with customPromisifyArgs does
not supply this ability.

I created a custom implementation and attached it to exec and execFile
using the util.promisify.custom key.

Note that I added stdout and stderr as regular enumerable
properties. I'm not sure that's the right decision.

Fixes: #13364

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines
Affected core subsystem(s)

child_process

@nodejs-github-bot nodejs-github-bot added the child_process Issues and PRs related to the child_process subsystem. label Jun 2, 2017
{ value: ['stdout', 'stderr'], enumerable: false });

Object.defineProperty(exports.exec, util.promisify.custom, {
enumerable: false, value: function(...args) {
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 we prefer breaking after the ,, and if you want, you can use the value(...args) { shorthand notation

});
return promise;
}
});
Copy link
Member

Choose a reason for hiding this comment

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

These two functions are nearly identical. It should be okay, but it shouldn’t be too hard to merge these, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will do

Object.defineProperty(exports.exec, util.promisify.custom, {
enumerable: false, value: function(...args) {
const promise = createPromise();
exports.exec.call(this, ...args, (err, stdout, stderr) => {
Copy link
Member

Choose a reason for hiding this comment

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

I don’t think you need to use .call; exec should work no matter what this refers to

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Definitely, that was my first all. And to use an arrow function instead of a regular function (as the property value). But then I looked at util.promisify and that's what it does, so I got all afraid that in some cases the this in exec may have some meaning.

OK - I'll refactor the value of the property into an arrow function + call exec regulary without .call.

@@ -32,3 +32,22 @@ const execFile = promisify(child_process.execFile);
assert(err.message.includes('doesntexist'));
}));
}
const failingCodeWithStdoutErr =
'console.log("out");console.error("err");process.exit(1)';
Copy link
Member

Choose a reason for hiding this comment

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

Some people have figured out that you can use template literals for getting good multiline JS code. :)

Copy link
Member

Choose a reason for hiding this comment

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

Very much not a fan of multiline termplate literals :-(

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I prefer not to - this string goes into the command line, and I have no idea what this will do there, especially not in windows.

const failingCodeWithStdoutErr =
'console.log("out");console.error("err");process.exit(1)';
{
exec(`${process.execPath} -e '${failingCodeWithStdoutErr}'`)
Copy link
Member

Choose a reason for hiding this comment

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

Does this work on Windows? I think there was some weirdness with single/double quotes. (If you don’t know, that’s okay; CI will tell us.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

"A wise man does not fall into a hole that a smart man can get out of" :-). I'll change it to output numbers and then use double quotes like the other tests.

@addaleax
Copy link
Member

addaleax commented Jun 2, 2017

Note that I added stdout and stderr as regular enumerable properties. I'm not sure that's the right decision.

It sounds like a good call to me; I think console.log() should print this kind of thing, for example.

@mscdex mscdex added the promises Issues and PRs related to ECMAScript promises. label Jun 2, 2017
Copy link
Member

@jasnell jasnell left a comment

Choose a reason for hiding this comment

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

LGTM with the reported nits fixed

@giltayar
Copy link
Contributor Author

giltayar commented Jun 2, 2017

Refactored according to all review comments, except for the multiline string comment, due to concern about Windows compatibility.

BTW, note that the kCustomPromisifyArgsSymbol introduced in util.promisify was used only for child_process.exec[File] and is now not used anywhere in the code.

@addaleax
Copy link
Member

addaleax commented Jun 2, 2017

This converts the initial implementation of a promised exec that used
the customPromisifyArgs support in util.promisify with a custom
implementation. This is because exec and execFile, when there is an
error, still supply the stdout and stderr of the process, and yet
the promisified version with customPromisifyArgs does
not supply this ability.

I created a custom implementation and attached it to exec and execFile
using the util.promisify.custom key.

Fixes: #13364
@giltayar
Copy link
Contributor Author

giltayar commented Jun 2, 2017

Sorry about that. Fixing - I had some weird git problems, that should now be resolved. Double-checking and then I'll push.

@giltayar
Copy link
Contributor Author

giltayar commented Jun 2, 2017

Hmm... nope, no weird git stuff. I did break the build (sorry...), but fixed it immediately after with a commit that fixed the bug. I double-checked and it's OK.

For some reason, the CI is marking that commit as failing, but when I click on the job, then it's building the previous commit, which should fail.

Maybe you should just run the CI again on this pull request?

@addaleax
Copy link
Member

addaleax commented Jun 2, 2017

For some reason, the CI is marking that commit as failing, but when I click on the job, then it's building the previous commit, which should fail.

Yes, the bot reports the results for the last commit in a PR, not the one which the build was actually started for. It’s a bit unfortunate.

Maybe you should just run the CI again on this pull request?

Yup. :)
CI: https://ci.nodejs.org/job/node-test-commit/10322/

@giltayar
Copy link
Contributor Author

giltayar commented Jun 2, 2017

It seems there's a problem in Windows. I'll dig up a Windows VM tomorrow and try and figure it out.

@addaleax
Copy link
Member

addaleax commented Jun 3, 2017

@giltayar
Copy link
Contributor Author

giltayar commented Jun 8, 2017

Anything additional I need to do here?

@addaleax
Copy link
Member

addaleax commented Jun 9, 2017

@giltayar Yes, ping us and ask whether there’s anything left to do. 😄

Landed in 8d7f07f, thanks for the PR! I tweaked the subject line of the commit a bit to get it under 50 characters.

@addaleax addaleax closed this Jun 9, 2017
addaleax pushed a commit that referenced this pull request Jun 9, 2017
This converts the initial implementation of a promised exec that used
the customPromisifyArgs support in util.promisify with a custom
implementation. This is because exec and execFile, when there is an
error, still supply the stdout and stderr of the process, and yet
the promisified version with customPromisifyArgs does
not supply this ability.

I created a custom implementation and attached it to exec and execFile
using the util.promisify.custom key.

Fixes: #13364
PR-URL: #13388
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
addaleax pushed a commit that referenced this pull request Jun 10, 2017
This converts the initial implementation of a promised exec that used
the customPromisifyArgs support in util.promisify with a custom
implementation. This is because exec and execFile, when there is an
error, still supply the stdout and stderr of the process, and yet
the promisified version with customPromisifyArgs does
not supply this ability.

I created a custom implementation and attached it to exec and execFile
using the util.promisify.custom key.

Fixes: #13364
PR-URL: #13388
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
addaleax added a commit that referenced this pull request Jun 10, 2017
* **Child processes**
  * `stdout` and `stderr` are now available on the error output of a
    failed call to the `util.promisify()`ed version of
    `child_process.exec`.
    [[`d66d4fc94c`](d66d4fc94c)]
    [#13388](#13388)

* **HTTPS**
  * The `rejectUnauthorized` option now works properly for unix sockets.
    [[`c4cbd99d37`](c4cbd99d37)]
    [#13505](#13505)

* **Readline**
  * A change that broke `npm init` and other code which uses `readline`
    multiple times on the same input stream is reverted.
    [[`0df6c0b5f0`](0df6c0b5f0)]
    [#13560](#13560)
@addaleax addaleax mentioned this pull request Jun 10, 2017
addaleax added a commit that referenced this pull request Jun 12, 2017
* **Child processes**
  * `stdout` and `stderr` are now available on the error output of a
    failed call to the `util.promisify()`ed version of
    `child_process.exec`.
    [[`d66d4fc94c`](d66d4fc94c)]
    [#13388](#13388)

* **HTTP**
  * A regression that broke certain scenarios in which HTTP is used together
    with the `cluster` module has been fixed.
    [[`fff8a56d6f`](fff8a56d6f)]
    [#13578](#13578)

* **HTTPS**
  * The `rejectUnauthorized` option now works properly for unix sockets.
    [[`c4cbd99d37`](c4cbd99d37)]
    [#13505](#13505)

* **Readline**
  * A change that broke `npm init` and other code which uses `readline`
    multiple times on the same input stream is reverted.
    [[`0df6c0b5f0`](0df6c0b5f0)]
    [#13560](#13560)

PR-URL: #13598
addaleax added a commit that referenced this pull request Jun 12, 2017
* **Child processes**
  * `stdout` and `stderr` are now available on the error output of a
    failed call to the `util.promisify()`ed version of
    `child_process.exec`.
    [[`d66d4fc94c`](d66d4fc94c)]
    [#13388](#13388)

* **HTTP**
  * A regression that broke certain scenarios in which HTTP is used together
    with the `cluster` module has been fixed.
    [[`fff8a56d6f`](fff8a56d6f)]
    [#13578](#13578)

* **HTTPS**
  * The `rejectUnauthorized` option now works properly for unix sockets.
    [[`c4cbd99d37`](c4cbd99d37)]
    [#13505](#13505)

* **Readline**
  * A change that broke `npm init` and other code which uses `readline`
    multiple times on the same input stream is reverted.
    [[`0df6c0b5f0`](0df6c0b5f0)]
    [#13560](#13560)

PR-URL: #13598
addaleax added a commit that referenced this pull request Jun 12, 2017
* **Child processes**
  * `stdout` and `stderr` are now available on the error output of a
    failed call to the `util.promisify()`ed version of
    `child_process.exec`.
    [[`d66d4fc94c`](d66d4fc94c)]
    [#13388](#13388)

* **HTTP**
  * A regression that broke certain scenarios in which HTTP is used together
    with the `cluster` module has been fixed.
    [[`fff8a56d6f`](fff8a56d6f)]
    [#13578](#13578)

* **HTTPS**
  * The `rejectUnauthorized` option now works properly for unix sockets.
    [[`c4cbd99d37`](c4cbd99d37)]
    [#13505](#13505)

* **Readline**
  * A change that broke `npm init` and other code which uses `readline`
    multiple times on the same input stream is reverted.
    [[`0df6c0b5f0`](0df6c0b5f0)]
    [#13560](#13560)

PR-URL: #13598
MylesBorins pushed a commit that referenced this pull request Jun 13, 2017
* **Child processes**
  * `stdout` and `stderr` are now available on the error output of a
    failed call to the `util.promisify()`ed version of
    `child_process.exec`.
    [[`d66d4fc94c`](d66d4fc94c)]
    [#13388](#13388)

* **HTTP**
  * A regression that broke certain scenarios in which HTTP is used together
    with the `cluster` module has been fixed.
    [[`fff8a56d6f`](fff8a56d6f)]
    [#13578](#13578)

* **HTTPS**
  * The `rejectUnauthorized` option now works properly for unix sockets.
    [[`c4cbd99d37`](c4cbd99d37)]
    [#13505](#13505)

* **Readline**
  * A change that broke `npm init` and other code which uses `readline`
    multiple times on the same input stream is reverted.
    [[`0df6c0b5f0`](0df6c0b5f0)]
    [#13560](#13560)

PR-URL: #13598
jasnell pushed a commit that referenced this pull request Jun 13, 2017
* **Child processes**
  * `stdout` and `stderr` are now available on the error output of a
    failed call to the `util.promisify()`ed version of
    `child_process.exec`.
    [[`d66d4fc94c`](d66d4fc94c)]
    [#13388](#13388)

* **HTTP**
  * A regression that broke certain scenarios in which HTTP is used together
    with the `cluster` module has been fixed.
    [[`fff8a56d6f`](fff8a56d6f)]
    [#13578](#13578)

* **HTTPS**
  * The `rejectUnauthorized` option now works properly for unix sockets.
    [[`c4cbd99d37`](c4cbd99d37)]
    [#13505](#13505)

* **Readline**
  * A change that broke `npm init` and other code which uses `readline`
    multiple times on the same input stream is reverted.
    [[`0df6c0b5f0`](0df6c0b5f0)]
    [#13560](#13560)

PR-URL: #13598
@gibfahn gibfahn mentioned this pull request Jun 15, 2017
3 tasks
@MylesBorins
Copy link
Contributor

Is this something we should backport to v6.x?

@giltayar
Copy link
Contributor Author

giltayar commented Jul 17, 2017 via email

@nicojs
Copy link

nicojs commented Oct 9, 2018

Given that util.promisify doesn't exist in v6.x, there's no need for this to be backported.

I'm trying to create a node6 compatible shim for util.promisify, so a backport would have been very useful to me.

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. promises Issues and PRs related to ECMAScript promises.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants