Fix child_process.kill oddities
* When the process is already dead, but the `exit` signal wasn't raised yet, the ESRCH error should be ignored. * When an invalid signal is specified, kill() should throw. * Like process.kill(), child_process.kill() now preserves a `0` signal which can be used to check the liveliness of the child process. * process.kill() and child_process.kill() will now return true if the signal was actually delivered, and false otherwise. * When an `exec`-ed process is automatically killed because a time or buffer limit is exceeded, and the kill() fails, this error should be reported through the `exec` callback. Fixes: #3409
This commit is contained in:
parent
b53b8b8ae7
commit
10f85fadfe
@ -536,12 +536,24 @@ exports.execFile = function(file /* args, options, callback */) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function errorhandler(e) {
|
||||||
|
err = e;
|
||||||
|
child.stdout.destroy();
|
||||||
|
child.stderr.destroy();
|
||||||
|
exithandler();
|
||||||
|
}
|
||||||
|
|
||||||
function kill() {
|
function kill() {
|
||||||
|
child.stdout.destroy();
|
||||||
|
child.stderr.destroy();
|
||||||
|
|
||||||
killed = true;
|
killed = true;
|
||||||
child.kill(options.killSignal);
|
try {
|
||||||
process.nextTick(function() {
|
child.kill(options.killSignal);
|
||||||
exithandler(null, options.killSignal);
|
} catch (e) {
|
||||||
});
|
err = e;
|
||||||
|
exithandler();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.timeout > 0) {
|
if (options.timeout > 0) {
|
||||||
@ -571,6 +583,7 @@ exports.execFile = function(file /* args, options, callback */) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
child.addListener('close', exithandler);
|
child.addListener('close', exithandler);
|
||||||
|
child.addListener('error', errorhandler);
|
||||||
|
|
||||||
return child;
|
return child;
|
||||||
};
|
};
|
||||||
@ -822,25 +835,43 @@ function errnoException(errorno, syscall, errmsg) {
|
|||||||
|
|
||||||
|
|
||||||
ChildProcess.prototype.kill = function(sig) {
|
ChildProcess.prototype.kill = function(sig) {
|
||||||
|
var signal;
|
||||||
|
|
||||||
if (!constants) {
|
if (!constants) {
|
||||||
constants = process.binding('constants');
|
constants = process.binding('constants');
|
||||||
}
|
}
|
||||||
|
|
||||||
sig = sig || 'SIGTERM';
|
if (sig === 0) {
|
||||||
var signal = constants[sig];
|
signal = 0;
|
||||||
|
} else if (!sig) {
|
||||||
|
signal = constants['SIGTERM'];
|
||||||
|
} else {
|
||||||
|
signal = constants[sig];
|
||||||
|
}
|
||||||
|
|
||||||
if (!signal) {
|
if (signal === undefined) {
|
||||||
throw new Error('Unknown signal: ' + sig);
|
throw new Error('Unknown signal: ' + sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._handle) {
|
if (this._handle) {
|
||||||
this.killed = true;
|
|
||||||
var r = this._handle.kill(signal);
|
var r = this._handle.kill(signal);
|
||||||
if (r === -1) {
|
if (r == 0) {
|
||||||
|
/* Success. */
|
||||||
|
this.killed = true;
|
||||||
|
return true;
|
||||||
|
} else if (errno == 'ESRCH') {
|
||||||
|
/* Already dead. */
|
||||||
|
} else if (errno == 'EINVAL' || errno == 'ENOSYS') {
|
||||||
|
/* The underlying platform doesn't support this signal. */
|
||||||
|
throw errnoException(errno, 'kill');
|
||||||
|
} else {
|
||||||
|
/* Other error, almost certainly EPERM. */
|
||||||
this.emit('error', errnoException(errno, 'kill'));
|
this.emit('error', errnoException(errno, 'kill'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Kill didn't succeed. */
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -430,6 +430,8 @@
|
|||||||
if (r) {
|
if (r) {
|
||||||
throw errnoException(errno, 'kill');
|
throw errnoException(errno, 'kill');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user