-
Notifications
You must be signed in to change notification settings - Fork 30.2k
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: support numeric signal argument to kill. #9651
Conversation
Awesome! Do you think you could get a test for this together? There’s a bit on that in https://github.com/nodejs/node/blob/master/doc/guides/writing_tests.md, but I’d assume there are existing tests for the string signal names in And a few tiny commit message things: Could you drop the |
Will do! |
ae7c0d4
to
29198d4
Compare
Thanks, apart from the missing tests this looks good! |
29198d4
to
410c589
Compare
There was an existing test for child-process-kill, so I made a copy of that test and modified it to send the numeric value of SIGTERM. I also modified the commit message as requested. I totally forgot to check that length before pushing. |
lib/internal/child_process.js
Outdated
@@ -356,6 +356,8 @@ ChildProcess.prototype.kill = function(sig) { | |||
signal = 0; | |||
} else if (!sig) { | |||
signal = constants['SIGTERM']; | |||
} else if (typeof sig === 'number') { |
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.
Couldn't this replace the if (sig === 0)
check a few lines up?
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, that makes more sense. Updated.
@@ -0,0 +1,42 @@ | |||
'use strict'; | |||
var common = require('../common'); |
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.
Please use const
instead of var
throughout the test.
var gotStdoutEOF = false; | ||
var gotStderrEOF = false; | ||
|
||
var cat = spawn(common.isWindows ? 'cmd' : 'cat'); |
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.
Could you use common.spawnCat()
?
var cat = spawn(common.isWindows ? 'cmd' : 'cat'); | ||
|
||
|
||
cat.stdout.on('end', function() { |
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.
Please add common.mustCall()
around the callback, then gotStdoutEOF
can be completely removed.
}); | ||
|
||
cat.stderr.on('data', function(chunk) { | ||
assert.ok(false); |
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.
Please use common.fail()
here.
assert.ok(false); | ||
}); | ||
|
||
cat.stderr.on('end', function() { |
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.
Please add common.mustCall()
around the callback, then gotStderrEOF can be completely removed.
gotStderrEOF = true; | ||
}); | ||
|
||
cat.on('exit', function(code, signal) { |
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.
Please use common.mustCall()
, and move the assertions for exitCode
and termSignal
here.
termSignal = signal; | ||
}); | ||
|
||
assert.equal(cat.killed, false); |
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.
assert.strictEqual()
please.
assert.equal(cat.killed, false); | ||
// numeric value of SIGTERM | ||
cat.kill(15); | ||
assert.equal(cat.killed, true); |
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.
assert.strictEqual()
again here, please.
cat.kill(15); | ||
assert.equal(cat.killed, true); | ||
|
||
process.on('exit', function() { |
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.
Once the common.mustCall()
changes are made, this can be removed completely.
@cjihrig Those changes are easy enough, but that will make this test very different than the existing child process kill test. Is that ok? |
The existing test is outdated, even if it's still technically correct. You can also check out the relatively new https://github.com/nodejs/node/blob/master/doc/guides/writing_tests.md. |
044fdec
to
7c08ce9
Compare
@cjihrig I think I've updated the test correctly. Can you take another look when you have a moment? Thanks for your patience! |
commit messages should not have a |
@sam-github The period in the commit message was removed based on feedback from @addaleax . |
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 commit is missing documentation.
lib/internal/child_process.js
Outdated
signal = constants['SIGTERM']; | ||
} else if (typeof sig === 'number') { |
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.
@cjihrig should we enforce integral, so 1.2
is not acceptable?
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.
@sam-github makes sense to me.
lib/internal/child_process.js
Outdated
if (sig === 0) { | ||
signal = 0; | ||
} else if (!sig) { | ||
if (!sig) { |
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.
did you test this? I'm pretty sure that 0
is now going to become SIGTERM
.
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.
Ouch! That's totally wrong. I didn't test 0
after making the suggested change. Will fix.
})); | ||
|
||
assert.strictEqual(cat.killed, false); | ||
// numeric value of SIGTERM |
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.
I think this could be constants.os.signals.SIGTERM
, so the comment would be unnecessary.
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.
Changed.
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 makes child.kill()
mysteriously different from process.kill()
, doesn't it? They should accept the same arguments.
lib/internal/child_process.js
Outdated
if (sig === 0) { | ||
signal = 0; | ||
} else if (!sig) { | ||
if (!sig) { |
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 condition has to be after typeof sig === 'number'
otherwise signal 0
will be incorrectly converted to SIGTERM
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.
Changed.
+1 on supporting numeric signals |
I didn't look around, but if there are existing tests for kill, it would be good to add this to them, it can be hard to find tests when there is one big test file that mostly tests a feature the a couple smaller ones sprinkled about that test the incremental additions that were made over time. ^---- I didn't look around, I'm just at the github review tool right now, if its not the case that there is a good test to extend, and this new test file is the best way, pls ignore. |
9ba3620
to
798fe20
Compare
@sam-github My lunch break is over, but if I can get the |
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.
LGTM
798fe20
to
5e8cdf9
Compare
@sam-github I took a cut at updating the docs and fixed a typo in that area. |
doc/api/child_process.md
Outdated
@@ -789,9 +789,10 @@ within the child process to close the IPC channel as well. | |||
added: v0.1.90 | |||
--> | |||
|
|||
* `signal` {String} | |||
* `signal` {String|number} The signal to send, either as a string or number. |
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.
String|number
-> String|Number
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.
Fixed! That was actually a c+p from process.md, so I'll add another commit to fix that file. Or should I open a different PR for that?
The test from this PR could be integrated with |
5e8cdf9
to
7c45e72
Compare
I'll combine the new test with the existing child process test tomorrow. |
Btw, I still object to adding numeric signal support to Also, I'm surprised child_process does its own arg checking at all, instead of calling https://github.com/nodejs/node/blob/master/lib/internal/process.js#L152-L178, so that the arg checks, Error strings, etc. would be provably identical. I don't have time to look further, but it looks to me like |
lib/internal/child_process.js
Outdated
if (sig === 0) { | ||
signal = 0; | ||
if (typeof sig === 'number') { | ||
signal = sig; |
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 should likely check that the value is not an invalid number. For instance:
typeof NaN === 'number'
typeof Infinity === 'number'
typeof 1.1 === 'number'
typeof -1 === 'number'
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.
typeof sig === 'number' && sig >>> 0 === sig
should probably do the trick.
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.
Awesome, you just taught me something. I've recently written similar code and used a bunch of ||
conditions.
Modified as requested.
76e52b8
to
04a8e74
Compare
@cjihrig I combined the tests as request, can you take a look? @sam-github I'll look into using |
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.
LGTM pending CI
04a8e74
to
fd7a620
Compare
@sam-github @targos could you take a look and update your reviews accordingly? |
@@ -1,4 +1,4 @@ | |||
# Child Process | |||
#n Child Process |
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.
@gerrard00 You have an extra n
here. :)
We can fix that on landing though.
The `child.kill()` methods sends a signal to the child process. If no argument | ||
is given, the process will be sent the `'SIGTERM'` signal. See signal(7) for | ||
The `child.kill()` method sends a signal to the child process. If no argument | ||
is given, the process will be sent the `'SIGTERM'` signal. See `signal(7)` for |
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.
I think we don't put backticks around man page references
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 getting fixed?
})); | ||
|
||
assert.equal(cat.killed, false); | ||
cat.kill(); |
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.
Shouldn't it pass sig
here?
} | ||
|
||
runTest(constants.os.signals.SIGTERM); | ||
runTest('SIGTERM'); |
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.
a third test can be added without an argument (to check the default value for signal)
My comment from #9651 (comment) still stands:
There is no reason to make these two Landing these kind of changes has historically been a source of node API weirdness, wherein two parts of the API subtlely diverge. There is no reason to do that here, lets just make it all better, consistently, at one time. |
@sam-github Ah, yes. I agree on that. |
@gerrard00 Are you still interested in getting this across the finish line? Adding |
I'll close this and work on a new PR based on the feedback provided. |
Actually #10423 covers implicitly this as well. |
Checklist
make -j8 test
(UNIX), orvcbuild test nosign
(Windows) passesAffected core subsystem(s)
child_process
Description of change
Modifies the kill function to support numeric signals. I used a type check instead of
Number.isInteger
because that was the pattern used elsewhere in the code base.Addresses: #9519