Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Feature/fix child process type checking #8454

Closed
wants to merge 5 commits into from
Closed

Feature/fix child process type checking #8454

wants to merge 5 commits into from

Conversation

sam-github
Copy link

#8392 introduced a test that doesn't fail when the code it is testing is deleted.

Also, behaviour of execFile and spawn have drifted apart again, unnecessarily, I think. This brings them into line again.

/to @cjihrig

errors = 0;

try {
// Ensure this throws a TypeError
var child = spawn(invalidcmd, 'this is not an array');
Copy link

Choose a reason for hiding this comment

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

Even before my changes, I think this test was a bit overkill. It intentionally ran a bad command and passed in bad arguments to make sure that the TypeError was thrown, and the invalid command error wasn't encountered. A simple assert.throws() like you've done would have been simpler. I'm fine with getting rid of this code.

Would you mind removing the the errors variable and the process.on('exit', ...)?

Copy link
Author

Choose a reason for hiding this comment

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

Not at all, I will do.

@sam-github
Copy link
Author

@tjfontaine @cjihrig PTAL

@@ -610,6 +612,8 @@ exports.execFile = function(file /* args, options, callback */) {
if (Array.isArray(arguments[1])) {
args = arguments[1];
options = util._extend(options, arguments[2]);
} else if (arguments[1] && typeof arguments[1] !== 'object') {
Copy link

Choose a reason for hiding this comment

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

I think this could cause problems in execFile() since arguments[1] could be a function too. Maybe throw in a check for arguments[1] !== callback

Choose a reason for hiding this comment

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

Correct. The callback is not being allowed to bubble down. This'll need to be fixed, but more than just adding a check. The values need to be assigned in that specific case. e.g.:

} else if (typeof arguments[1] === 'function') {
  callback = arguments[1];
  args = [];
} else if (arguments[1] && typeof arguments[1] !== 'object') {

Though this does leave the possibility of the user passing 0 to arguments[1] and still not throwing. Instead I'd use the following:

} else if (arguments[1] && typeof arguments[1] === 'object') {
  args = [];
  options = util._extend(options, arguments[1]);
} else {
  throw new TypeError('Incorrect value of args option');
}

@sam-github
Copy link
Author

I popped off the rename, 939c897, because it makes addressing comments hard without rebasing them away, I'll add it back after review.

@sam-github
Copy link
Author

Addressed comments (and incorporated #8530).
PTAL.

@trevnorris
Copy link

Applied this to v0.10. Here are some of the following errors:

=== release test-child-process-exec-error ===                          
Path: simple/test-child-process-exec-error
assert.js:92
  throw new assert.AssertionError({
        ^
AssertionError: 0 == 1
    at process.<anonymous> (/var/projects/node/test/simple/test-child-process-exec-error.js:35:12)
    at process.emit (events.js:117:20)
Command: out/Release/node /var/projects/node/test/simple/test-child-process-exec-error.js
=== release test-child-process-exit-code ===                    
Path: simple/test-child-process-exit-code
assert.js:92
  throw new assert.AssertionError({
        ^
AssertionError: false == true
    at ChildProcess.<anonymous> (/var/projects/node/test/simple/test-child-process-exit-code.js:44:10)
    at ChildProcess.emit (events.js:98:17)
    at Process.ChildProcess._handle.onexit (child_process.js:814:12)
Command: out/Release/node /var/projects/node/test/simple/test-child-process-exit-code.js
=== release test-error-reporting ===                                  
Path: simple/test-error-reporting
assert.js:92
  throw new assert.AssertionError({
        ^
AssertionError: 3 == 0
    at process.<anonymous> (/var/projects/node/test/simple/test-error-reporting.js:75:10)
    at process.emit (events.js:117:20)
Command: out/Release/node /var/projects/node/test/simple/test-error-reporting.js

@sam-github
Copy link
Author

Sorry, @trevnorris, those tests pass for me on Linux, what's your platform?

And what did you mean by "applied to v0.10"? This PR is off the current head of v0.10... did you mean you applied it to v0.12? It doesn't apply clean to that branch.

I could rebase it onto it, and re-PR, of course. There are 3 branches in play, its hard to know where to direct PRs. I could even do one PR to v0.10, and another to v0.12, so that fixing the conflicts would be my problem, but I'm not really sure how helpful that would be.

@sam-github
Copy link
Author

@trevnorris ping

@trevnorris
Copy link

@sam-github Thanks for the ping. The mention of applying it to v0.10 was meant to say it was applied to the tip of v0.10, since the PR hadn't been rebased on the latest. There's no need to re-PR for just rebasing on latest v0.10. Just rebase and force push your branch.

I'm rerunning the tests and will update with the results. My platform is Linux 3.16.0-24-generic #32-Ubuntu

@trevnorris
Copy link

The tests are still failing. Here's a strange one. Apply the following patch:

diff --git a/test/simple/test-child-process-exec-error.js b/test/simple/test-child-process-exec-error.js
index 2afe114..1f9d6f5 100644
--- a/test/simple/test-child-process-exec-error.js
+++ b/test/simple/test-child-process-exec-error.js
@@ -29,9 +29,11 @@ function test(fun, code) {
   fun('does-not-exist', function(err) {
     assert.equal(err.code, code);
     errors++;
+    console.log('>>> fun executed', process.pid, errors);
   });

   process.on('exit', function() {
+    console.log('>>> process exiting', process.pid, errors);
     assert.equal(errors, 1);
   });
 }

And the output I get is:

>>> fun executed 22943 1
>>> process exiting 22943 0

assert.js:93
  throw new assert.AssertionError({
        ^
AssertionError: 0 == 1
    at process.<anonymous> (/var/projects/node/test/simple/test-child-process-exec-error.js:37:12)
    at process.emit (events.js:117:20)

But if I move the var error = 0 outside of function test() then the output is:

>>> fun executed 22989 1
>>> process exiting 22989 1
>>> process exiting 22989 1

Any ideas what's going on?

Its common knowledge on unix, but node documentation depends on knowing
this, as it exposes both streams named after stdio, and the fd numbers,
so make this explicit.

Closes #8624
The test wasn't checking directly that an assertion was thrown. Instead,
it was checking that spawn did not sucessfully spawn a non-existent
command.

However, the command chosen, dir, exists in GNU coreutils, so it exists
on Linux (though not on BSD derived OS X). The test as written passed on
Linux, even with the TypeError it is supposed to be checking for deleted
from spawn(). It would also pass on Windows if a ls.exe existed.

The approach is unnecessarily obscure, `assert.throw()` is for asserting
code throws, using it is more clear and works regardless of what
commands do or do not exist.
@sam-github
Copy link
Author

@trevnorris yes, I've figured out the problem, I'll see if I can fix it. I think checking types of args may not be possible for functions that have 4 args, 3 of which are optional.

execFile and spawn have same API signature with respect to optional arg
array and optional options object, they should have same behaviour with
respect to argument validation.
Optional fork args should be type-checked with same behaviour as the
equivalent argument to spawn.
@sam-github
Copy link
Author

@trevnorris fixed, and added regression tests. I wasn't dealing with unsigned/null as explicit "no option" place holders in the postitional list, and exec uses this feature when it calls execFile. Thanks for catching that.

@trevnorris
Copy link

Awesome work. I'm getting a timeout on test-cluster-dgram-1.js, but double checking that's not actually part of your code (not sure how it could be). Also there are a couple JS style issues (can see those w/ make jslint) but I can fix those up when I squash and land.

trevnorris pushed a commit that referenced this pull request Nov 19, 2014
Its common knowledge on unix, but node documentation depends on knowing
this, as it exposes both streams named after stdio, and the fd numbers,
so make this explicit.

Fixes: #8624
PR-URL: #8454
Reviewed-by: Trevor Norris <[email protected]>
trevnorris pushed a commit that referenced this pull request Nov 19, 2014
The test wasn't checking directly that an assertion was thrown. Instead,
it was checking that spawn did not sucessfully spawn a non-existent
command.

However, the command chosen, dir, exists in GNU coreutils, so it exists
on Linux (though not on BSD derived OS X). The test as written passed on
Linux, even with the TypeError it is supposed to be checking for deleted
from spawn(). It would also pass on Windows if a ls.exe existed.

The approach is unnecessarily obscure, assert.throw() is for asserting
code throws, using it is more clear and works regardless of what
commands do or do not exist.

PR-URL: #8454
Reviewed-by: Trevor Norris <[email protected]>
trevnorris pushed a commit that referenced this pull request Nov 19, 2014
execFile and spawn have same API signature with respect to optional arg
array and optional options object, they should have same behaviour with
respect to argument validation.

PR-URL: #8454
Reviewed-by: Trevor Norris <[email protected]>
trevnorris pushed a commit that referenced this pull request Nov 19, 2014
Optional fork args should be type-checked with same behaviour as the
equivalent argument to spawn.

PR-URL: #8454
Reviewed-by: Trevor Norris <[email protected]>
trevnorris pushed a commit that referenced this pull request Nov 19, 2014
@trevnorris
Copy link

Thanks much. Landed in 13a992b1, 2ff29cc, e17c5a7, 70dafa7 and 8032a21.

@trevnorris trevnorris closed this Nov 19, 2014
@sam-github
Copy link
Author

@trevnorris I'll make sure to run jshint more regularly, sorry about that.

cjihrig added a commit that referenced this pull request Dec 17, 2014
A block of asserts were duplicated in
test/simple/test-child-process-spawn-typeerror.js. This commit
removes the duplicated asserts.

Fixes: #8454
Reviewed-By: Colin Ihrig <[email protected]>
@sam-github sam-github deleted the feature/fix-child-process-type-checking branch December 23, 2014 19:23
mscdex pushed a commit to mscdex/node that referenced this pull request Dec 25, 2014
Its common knowledge on unix, but node documentation depends on knowing
this, as it exposes both streams named after stdio, and the fd numbers,
so make this explicit.

Fixes: nodejs#8624
PR-URL: nodejs#8454
Reviewed-by: Trevor Norris <[email protected]>
mscdex pushed a commit to mscdex/node that referenced this pull request Dec 25, 2014
The test wasn't checking directly that an assertion was thrown. Instead,
it was checking that spawn did not sucessfully spawn a non-existent
command.

However, the command chosen, dir, exists in GNU coreutils, so it exists
on Linux (though not on BSD derived OS X). The test as written passed on
Linux, even with the TypeError it is supposed to be checking for deleted
from spawn(). It would also pass on Windows if a ls.exe existed.

The approach is unnecessarily obscure, assert.throw() is for asserting
code throws, using it is more clear and works regardless of what
commands do or do not exist.

PR-URL: nodejs#8454
Reviewed-by: Trevor Norris <[email protected]>
mscdex pushed a commit to mscdex/node that referenced this pull request Dec 25, 2014
execFile and spawn have same API signature with respect to optional arg
array and optional options object, they should have same behaviour with
respect to argument validation.

PR-URL: nodejs#8454
Reviewed-by: Trevor Norris <[email protected]>
mscdex pushed a commit to mscdex/node that referenced this pull request Dec 25, 2014
Optional fork args should be type-checked with same behaviour as the
equivalent argument to spawn.

PR-URL: nodejs#8454
Reviewed-by: Trevor Norris <[email protected]>
mscdex pushed a commit to mscdex/node that referenced this pull request Dec 25, 2014
mscdex pushed a commit to mscdex/node that referenced this pull request Dec 25, 2014
A block of asserts were duplicated in
test/simple/test-child-process-spawn-typeerror.js. This commit
removes the duplicated asserts.

Fixes: nodejs#8454
Reviewed-By: Colin Ihrig <[email protected]>
piscisaureus pushed a commit to piscisaureus/node2 that referenced this pull request Jan 10, 2015
Its common knowledge on unix, but node documentation depends on knowing
this, as it exposes both streams named after stdio, and the fd numbers,
so make this explicit.

Fixes: nodejs/node-v0.x-archive#8624
PR-URL: nodejs/node-v0.x-archive#8454
Reviewed-by: Trevor Norris <[email protected]>

Cherry-picked-from: nodejs/node-v0.x-archive@13a992b
piscisaureus added a commit to nodejs/node that referenced this pull request Jan 10, 2015
commit 709558ce0d4027978a742c618d014e5713422263
Author: cjihrig <[email protected]>
Date:   Wed Dec 17 14:58:09 2014 -0500

    test: remove redundant code in test

    A block of asserts were duplicated in
    test/simple/test-child-process-spawn-typeerror.js. This commit
    removes the duplicated asserts.

    Fixes: nodejs/node-v0.x-archive#8454
    Reviewed-By: Colin Ihrig <[email protected]>

commit 9e6d2792ae2eb3ad8553192a1d9c7a7d58808123
Author: Trevor Norris <[email protected]>
Date:   Tue Nov 18 16:42:10 2014 -0800

    lint: fix lint issues

    Forgot to fix these before landing the patch.

    Fixes: e17c5a7

commit 756612776e6bb6b4329a132948f40ad9c28555e2
Author: Sam Roberts <[email protected]>
Date:   Wed Oct 8 13:30:38 2014 -0700

    test: test all spawn parameter positions

    PR-URL: nodejs/node-v0.x-archive#8454
    Reviewed-by: Trevor Norris <[email protected]>

commit 408812653153cc50f626c7c69b2f8ea4a4be8cec
Author: Sam Roberts <[email protected]>
Date:   Mon Sep 29 11:26:43 2014 -0700

    child_process: check fork args is an array

    Optional fork args should be type-checked with same behaviour as the
    equivalent argument to spawn.

    PR-URL: nodejs/node-v0.x-archive#8454
    Reviewed-by: Trevor Norris <[email protected]>

commit 11bff9beb2f837a923eb0e515331303f7771301e
Author: Sam Roberts <[email protected]>
Date:   Thu Sep 25 22:28:33 2014 -0700

    child_process: check execFile args is an array

    execFile and spawn have same API signature with respect to optional arg
    array and optional options object, they should have same behaviour with
    respect to argument validation.

    PR-URL: nodejs/node-v0.x-archive#8454
    Reviewed-by: Trevor Norris <[email protected]>

commit d531ab78c41019f6fdcaf08a1e84ab2b9e439c1b
Author: cjihrig <[email protected]>
Date:   Wed Sep 17 17:26:46 2014 -0400

    child_process: properly support optional args

    Currently, a TypeError is incorrectly thrown if the second argument is
    an object. This commit allows the args argument to be properly omitted.

    Fixes: nodejs/node-v0.x-archive#6068
    Reviewed-by: Trevor Norris <[email protected]>
piscisaureus pushed a commit to nodejs/node that referenced this pull request Jan 13, 2015
The test wasn't checking directly that an assertion was thrown. Instead,
it was checking that spawn did not sucessfully spawn a non-existent
command.

However, the command chosen, dir, exists in GNU coreutils, so it exists
on Linux (though not on BSD derived OS X). The test as written passed on
Linux, even with the TypeError it is supposed to be checking for deleted
from spawn(). It would also pass on Windows if a ls.exe existed.

The approach is unnecessarily obscure, assert.throw() is for asserting
code throws, using it is more clear and works regardless of what
commands do or do not exist.

PR-URL: nodejs/node-v0.x-archive#8454
Reviewed-by: Trevor Norris <[email protected]>

Cherry-picked-from: nodejs/node-v0.x-archive@2ff29cc

Conflicts:
	test/parallel/test-child-process-spawn-typeerror.js
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants