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
Remove separate "internal error" from exec #802
Conversation
test/exec.js
Outdated
@@ -35,7 +35,7 @@ test('config.fatal and unknown command', t => { | |||
shell.config.fatal = true; | |||
t.throws(() => { | |||
shell.exec('asdfasdf'); // could not find command | |||
}, /exec: internal error/); | |||
}, /((asdfasdf: not found)|(asdfasdf: command not found)|('asdfasdf' is not recognized))/); |
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.
Why 3 regexes? If these are different shells, let's put a comment.
Should we check it's a shelljsinternalerror?
test/exec.js
Outdated
t.truthy(shell.error()); | ||
const err = t.throws(() => { | ||
shell.exec(`${JSON.stringify(shell.config.execPath)} test/resources/exec/slow.js 100`, { timeout: 10 }); // times out | ||
}, /ENOENT: no such file or directory/); |
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.
Oh, let's actually debug this. This looks like a real bug
Wow, this is a huge improvement. For curiosity, what do the stack traces look like for these errors? |
The stdout and stderr files may never be opened or written to in certain circumstances. In particular, if the timeout is short enough, the child node process does not have enough time to start, and the child script does not execute, so the files are not written to. So, catch errors form trying to read the files, and ignore them.
src/exec.js
Outdated
if (opts.encoding === 'buffer') { | ||
stdout = fs.readFileSync(stdoutFile); | ||
stderr = fs.readFileSync(stderrFile); | ||
try { stdout = fs.readFileSync(stdoutFile); } catch (e) {} |
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 this really the right fix? Why aren't the files created by the child process? I think that's where the bug really is.
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.
In the unit test specifically, the timeout is set to 10 ms, and node doesn't startup in that time. The code in exec-child.js
is what is creating the stdout and stderr files, and so if node hasn't started, then the files will not exist after the execSync
call exits.
Perhaps instead the files should be created before the execSync
call, and the child process just writes to them?
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.
This sort of bug usually means that the exec()
call inside exec-child.js
throws an exception:
Line 19 in 8ab0a3a
var c = childProcess.exec(cmd, execOptions, function (err) { |
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.
Oh, didn't see your last message. Huh, if node
doesn't startup, then I think we have a few options:
- Don't try to handle this, let it be an internal error
- Modify the test's timeout so that we're more confident
node
can start up - Create files beforehand (but this isn't really necessary in the common case, seems like a waste)
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.
This test case is all about checking the timeout
option works. So we can also try something like:
echo start
sleep 5
echo stop # Check that this doesn't print, because we timeout before this
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.
Sorry for the delay, I'll work on this soon.
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 rush. I think it's fine to wrap this into v0.9 anyway
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.
The test passes when the timeout is set to 500 ms (minus the try/catch
statements).If you think it's alright, I will just increase the timeout on the test.
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.
You mean to revert the try-catch statements here and to change the test timeout instead? I think that's fine.
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.
Ok, I'll go ahead with this.
test/exec.js
Outdated
}, /exec: internal error/); | ||
// the expected message depends on where tests are run: | ||
// /bin/sh says "foo: not found" | ||
// /bin/bash says "foo: command not found" |
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.
We only need to support /bin/sh
and cmd.exe
, since these are the default shells. I think error messages are implementation specific, so let's just limit it to those 2 if we can get away with it (so long as mac, linux, and windows bots are happy).
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.
On my machine, at least, /bin/sh
is the default shell, but the message is different than /bin/sh
on linux.
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.
How about we regex for asdfasdf
instead? I think that's good enough.
src/exec.js
Outdated
if (opts.encoding === 'buffer') { | ||
stdout = fs.readFileSync(stdoutFile); | ||
stderr = fs.readFileSync(stderrFile); | ||
try { stdout = fs.readFileSync(stdoutFile); } catch (e) {} |
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.
You mean to revert the try-catch statements here and to change the test timeout instead? I think that's fine.
@freitagbr any idea why we have travis failures? |
Ah, I tried it locally. It looks like |
Codecov Report
@@ Coverage Diff @@
## master #802 +/- ##
==========================================
+ Coverage 95.47% 95.81% +0.33%
==========================================
Files 34 34
Lines 1260 1361 +101
==========================================
+ Hits 1203 1304 +101
Misses 57 57
Continue to review full report at Codecov.
|
LGTM. Could you add a comment explaining that |
Sure, I will do that. Also, this is a breaking change, so do we want to land this on a development branch? i.e. landing in |
I don't think this is really breaking anything. The behavior changes I see are:
If you agree, feel free to merge |
@nfischer I'm really interested in getting this fix. Any indication of when 0.8.2 will be coming out? |
Fixes #734
Removes
common.error('internal error')
fromexec
, allowing any internal errors inexec
to be wrapped byShellJSInternalError
instead.