Unknown signal error as I try to kill a process - node.js

I am trying to kill a process using the kill method in child_process. But I get the following error as I try to call the function:
TypeError [ERR_UNKNOWN_SIGNAL]: Unknown signal: 18408
I am doing as follows:
const ls = spawn('node',['print']);
ls.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
});
ls.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
setTimeout(() => {
ls.kill(ls.pid);
},4000);
What could be the reason for this? What am I missing?

kill() sends a Unix signal. These are represented by numbers. You should pass the number of a signal to kill(), not the PID.
Try
import signal
print(signal.SIGTERM)
That probably prints 15 which is the number of the signal TERM (which normally terminates the process it is sent to).
In your program you could call
ls.kill(signal.SIGTERM)

In fact, unlike the Linux kill() command, which takes the process pid to kill and a signal as parameters, Nodejs ChildProcess subprocess.kill() expects only the signal argument (as string according to the documentation).
subprocess.kill([signal])
That makes sense because the subprocess already knows its pid (the one you get when using subprocess.pid) so you don't need to provide it again.
To kill your process, you can pass a valid signal to the .kill() method:
ls.kill('SIGTERM');
Or, you could also simply call the .kill() method of your subprocess without any arguments, which is equivalent to call it with the 'SIGTERM' signal.
ls.kill()

Related

Pass : (Colon) into child_process SPAWN arg

I have a command
omxplayer /home/pi/videos/9886a3n2545r7i505rzz.mp4 -o alsa:sysdefault
It runs fine from the command line, but if I translate that command to a spawn command:
let omxProcess = spawn('omxplayer', ['/home/pi/videos/9886a3n2545r7i505rzz.mp4', '-o', 'alsa:sysdefault'])
The command fails (without any error).
But if I run the following removing the :sysdefault it runs (But without the :sysdefault, the command is not the same and I need to run it with :sysdefault
let omxProcess = spawn('omxplayer', ['/home/pi/videos/9886a3n2545r7i505rzz.mp4', '-o', 'alsa'])
I'm thinking it has to do with having an ":" in the arg.
Any thoughts?
Since you're not using the shell: true flag, it's almost certainly not caused by the : in the command. You can always verify this, just to be on the safe side.
An easy way to check if the environment is messing with your arguments is calling another binary, for example echo, instead of omxplayer. Does it echo back your arguments? Is the colon still there?
The binary is probably exitting with some error code (and possibly an error message). To capture them, be sure to register handlers on the output streams, as well as an exit handler that should tell you the exit code. This is outlined in the child_process docs, right below spawn(). Adapted for your case:
omxProcess.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
omxProcess.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
omxProcess.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
Based on the output and the exit code, you should be able to debug the issue.

Child process isn't logging when receiving SIGINT

I am trying to kill a previously forked child process in Node.js. I'm unsure if it's working because my console.log line is not being hit in the child process.
Here is what I'm calling from the parent:
console.log("sending SIGINT from main");
child.kill("SIGINT");
And in the child:
process.on("SIGINT", () => {
console.log("Killing bot");
DBS.Bot.destroy();
process.exit();
});
The only console log I see is from the parent.
When spawning a NodeJS child process, this child process' stdout is not the same as the parent process' stdout stream, which is why you do not see any logging output. You can add the following code to copy any output of your child process to your main process' stdout stream:
child.stdout.on ("data", (data) => {
console.log ("child process: " + data.toString ());
});
In some circumstances, it can be useful to also capture stderr output, which is the stream NodeJS' console.err () writes to:
child.stderr.on ("data", (data) => {
console.log ("child process error: " + data.toString ());
});
Also, to make sure a child process has exited with a non-error code, i.e. the exit code is 0, you can use NodeJS' child_process "exit" signal:
child.on ("exit", (code, signal) => {
if (signal !== null) console.log ("child exited due to signal '" + signal + "'");
else console.log ("child exited with code " + code);
});
For more information, make sure to check out NodeJS' documenation on child_process.

Node.js child process exits with SIGTERM

I'm spawning a child process using Node 6.9.
const child = require('child_process').execFile('command', args);
child.stdout.on('data', (data) => {
console.log('child:', data);
});
child.stderr.on('data', (data) => {
console.log('child:', data);
});
child.on('close', (code, signal) => {
console.log(`ERROR: child terminated. Exit code: ${code}, signal: ${signal}`);
});
My child process runs for ~1m 30s but then I get this output from my Node.js program:
ERROR: child terminated. Exit code: null, signal: SIGTERM
What terminates my child process and why?
Edit:
I've added killSignal: 'SIGILL' as an option.
var child = require('child_process').execFile('geth', args, { killSignal: 'SIGILL'});
Now, I get this:
ERROR: go-ethereum terminated. Exit code: 2, signal: null
I found the problem and a solution.
From https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_child_process_execfile_file_args_options_callback
maxBuffer largest amount of data (in bytes) allowed on stdout or stderr - if exceeded child process is killed (Default: 200*1024)
I can set the maxBuffer option higher.
childProcess.execFile('geth', args, { maxBuffer: 400 * 1024});
It seems you can't disable the maxBuffer option, not even by setting it to 0. But it seems to be on purpose.

how detect if node.js spawn need input?

detect state of spawn process if is sleeping in an uninterruptible wait. by node.js windows.
// possible values for State value in /proc/pid/status
// R running,
// S is sleeping,
// D is sleeping in an uninterruptible wait,
// Z is zombie (not running but held by process owner)
// T is traced or stopped
var spawn = require("child_process").spawn;
var sh = spawn("java", ["Test"]);
sh.stdout.setEncoding("utf8");
sh.stderr.setEncoding("utf8");
sh.stdin.pipe(process.stdin);
sh.stdout.on('data', function(data) {
console.log(data);
if () {//check if sh need input
sh.stdin.write("ddssd");
sh.stdin.end();
}
});
sh.on('exit', function(ecode) {
console.log(ecode);
});
sh.stderr.on("data", (data) => {
console.log(data);
});
You don't need to detect that. If it needs input, you can just write to the stdin and it will read it when it needs it -- if it is able to read from stdin at all like that. If that doesn't work, the Java program may think it doesn't have an interactive terminal. In that case, you can try pty.js.

Node: Read spawn stderr/stdout after quick exit event?

I'm using Node's spawn to create a new process. Sometimes this process will exit very quickly with an error code and a message on stderr. It appears that stderr is getting lost in this quick turnaround. I've tried this:
reader.stderr.on('data', function (buf) {
console.log('stderr message: ' + buf);
});
reader.on('exit', function (code, signal) {
console.log('Exit');
});
Output:
Exit
stderr message: ERROR: Missing required option for command.
I also tried reading it in the exit listener, but no luck:
reader.on('exit', function (code, signal) {
console.log('Exit');
console.log('stderr: ' + reader.stderr.read());
});
Output:
Exit
stderr: null
So, it appears the problem is that the stderr output is too slow, and is late after the exit event where I need that information. How can I fix this?
Taken from the child_process docs for exit:
Note that the child process stdio streams might still be open.
They then describe the close event:
This event is emitted when the stdio streams of a child process have all terminated. This is distinct from 'exit', since multiple processes might share the same stdio streams.
So it looks like you should be using close, not exit.

Resources