Nodejs Terminate Spawned Child Process - node.js

I started a child process for a jar file by
var exec = require('child_process').exec;
// Start child process
var child = exec("java -jar test.jar");
and I terminated the child process by using a kill function that I wrote given the pid of the child
killProcess(child.pid);
The function always work when the pid is correct, however, because nodejs created the child process inside a cmd.exe shown in the picture below,
and the child.pid is the pid for the cmd.exe not the actual java.exe
My problem is that, occasionally, the java.exe will get too large and jump out of the cmd.exe and become an independent process, and I can't terminate it even when I stop the server. And because I don't have the pid of the java.exe I can't terminate it with my function.
What other ways can I terminate the process without doing it manually, or get the pid of the java.exe and not the cmd.exe?

It turns out, the problem is with the way how I create the child process.
Creating child process with exec has a size limit, thus, change it from exec to spawn solves the problem.
// Spawn the external jar file as a child process and listen print the output
var spawn = require('child_process').spawn;
// Start child process
var child = spawn('java', ['-jar', file_name]);

Related

Recommend way to kill child process for VS Code Extension

I have created a child process that I am trying to kill by process id.
const { spawn } = require('child_process');
let child = spawn("powershell.exe", 'file1.ps1', { detached: false });
process.kill(child.pid, 'SIGINT');
The use of standard POSIX signals like SIGINT or SIGKILL can kill the child process but causes 'Extension host terminated unexpectedly' error. After this none of the registered commands works for that extension. It produce "Command 'extension.commandName' not found" error.
Note: All the registered command is pushed in context.subscriptions and deactivate() method is also in place. I am trying it against Windows.

Node child process doesn't release port, even after it's killed by parent

I have a parent node process and a child node process. The child binds a web server to port 5000. The parent sometimes kills and restarts the child (usually because a file has changed).
The problem is: when the second child process starts, I get Error: listen EADDRINUSE :::5000.
The weird thing is, I kill the child process with child.kill(), then I wait for it to fire a close event, and then I wait 5 seconds with setTimeout, before trying to start a new child process...yet it always complains that the port is occupied. But if I manually kill the parent process (ctrl+C in my terminal) and run it again, I don't get the error. So killing the parent seems to be the only way to successfully release the port.
Can anyone think of a reason why this would happen? Why does the port remain occupied after the process that bound it is killed, until its parent process stops?
Actually it block the process so you need to kill the process by following command just type
ps -ax
You will get list of processes from where you need to check the process id which is been blocked then kill the process by this command
kill -9 processId
Kill all your running port by below command.
pkill node

Can't kill child process on Windows

The following will never exit
var child_process = require('child_process');
var ps = child_process.spawn('.\\node_modules\\.bin\\babel.cmd', ['input.js', '--out-file', 'output.js', '--watch']);
ps.on('exit', function() {
console.log('exit');
});
ps.on('close', function() {
console.log('close');
});
setTimeout(function () {
ps.kill();
}, 2000);
What's going on here? also what is the correct thing to do here? The only way to make this process actually close is to kill the parent process. I suspect it's waiting for stdio to flush or something like that?
It does die if it is given an 'ignore' stdio configuration, but I need the streams.
var ps = child_process.spawn('.\\node_modules\\.bin\\babel.cmd', ['test.js', '--out-file', 'output.js', '--watch'], {
stdio: 'ignore'
});
You are spawning child process cmd.exe by using babel.cmd. This process then starts another grandchild process node and runs babel script. When you do ps.kill() it only kills the cmd.exe but not the child processes created by it.
Although cmd.exe is closed, the stdio stream of the parent process is still shared with the other processes in the tree. So the parent process is waiting for the stream to be closed. Using stdio: 'ignore' will only stop sharing the stdio stream with other processes in the tree but those grandchild processes will still continue running.
Update:
After discussing with OP, I tested with all three stdio options: pipe(default), inherit, ignore in iojs 3.3.0, Windows 7 (32bit). None of them kills the grandchild process.
With inherit and ignore, both parent process and child process(cmd.exe) are killed but the grand child process still floats around and doesn't belong to any process tree.
With pipe, only the child process is terminated but both parent and grand child process continue running. The reason that parent process is not exiting is most likely because the stdio of parent node.exe is still shared with the other processes as mentioned in original answer.
child.unref() doesn't have any effect on killing grand child process. It only removes the child process from parent's event loop so that the parent process can exit normally.
I could think of couple of solutions:
Invoke the babel.js directly without that cmd script:
var ps = child_process.spawn('node', ['.\\node_modules\\babel\\bin\\babel.js', 'input.js', '--out-file', 'output.js', '--watch'])
Use windows taskkill command with \T flag to kill the process and all the child processes started by it:
os = require('os');
if(os.platform() === 'win32'){
child_process.exec('taskkill /pid ' + ps.pid + ' /T /F')
}else{
ps.kill();
}
There are some npm modules that can handle killing child processes in both Unix and Windows e.g. tree-kill. For windows it uses taskkill or tasklist.
I have the same issue on Windows (Win 10 64x). I can't terminate a process of a spawned child process.
I start a service (custom HTTP server service.windows) using child_process.spawn():
const { spawn } = require('child_process');
let cp = spawn('"C:\\Users\\user\\app\\service.windows"', [], { shell: true, });
cp.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
console.log('cp.connected', cp.connected);
console.log('process.pid', process.pid); // 6632 <<= main node.js PID
console.log('cp.pid', cp.pid); // 9424 <<= child PID
// All these are useless, they just kill `cp`
cp.kill('SIGINT'); // Doesn't terminate service.windows
cp.kill('SIGKILL'); // Doesn't terminate service.windows
cp.kill('SIGTERM'); // Doesn't terminate service.windows
});
And I want to terminate my HTTP server service (service.windows). And it is not possible on Windows using cp.kill('ANY SIGNAL'). Node.js kills its child process (cp) but my HTTP server (service.windows) still runs fine.
When I check it in other terminal, I see my server is running just fine:
$ netstat -ano | findstr :9090
TCP 0.0.0.0:9090 0.0.0.0:0 LISTENING 1340
TCP [::]:9090 [::]:0 LISTENING 1340
I try manually kill my server by PID but with T flag, not F. The difference:
T terminate all child processes along with the parent process, commonly known as a tree kill.
F process(es) be forcefully terminated.
$ taskkill -T -PID 1340
ERROR: The process with PID 1340 (child process of PID 9424) could not be terminated.
Reason: This process can only be terminated forcefully (with /F option).
And it exactly says that my server 1340 is a child of that cp - PID 9424.
OK, I try to terminate that cp using T flag again. And boom, not possible. cp is a child of my main node.js process.pid 6632:
$ taskkill -T -PID 9424
ERROR: The process with PID 1340 (child process of PID 9424) could not be terminated.
Reason: This process can only be terminated forcefully (with /F option).
ERROR: The process with PID 9424 (child process of PID 6632) could not be terminated.
Reason: One or more child processes of this process were still running.
I can only kill it forcefully with F flag:
$ taskkill -F -T -PID 9424
SUCCESS: The process with PID 1340 (child process of PID 9424) has been terminated.
SUCCESS: The process with PID 9424 (child process of PID 6632) has been terminated.
Most disappointing thing is that Node.js docs doesn't say jack ship about how to deal with this issue. They only say "yes, we know the issue exist and we just inform you about it".
The only option I see on Windows is to use taskkill -F -T -PID 9424 in spawned process:
exec('taskkill -F -T -PID 9424');
One potential solution is to call ReadableStream.end or ReadableStream.destroy
The most straight forward solution, don't spawn scripts instead spawn node directly.
For unix, the script is the npm executable. For windows however we need to resolve the name from the .cmd file.
if (path.extname(command).toLowerCase() == '.cmd') {
var content = '' + fs.readFileSync(command);
var link = (/node "%~dp0\\(.*?)"/.exec(content) || [])[1];
if (link) {
command = path.resolve(path.dirname(command), link);
}
}
var ps = child.spawn('node', [command].concat(args), options);
For me, my process was spawn of cmd.exe with the args:
/s /c start /B /I /belownormal ffmpeg.exe -hide_banner -i somevideo.mp4 -vn -ar 48000 -ac 2 -c:a pcm_s16le -f wav -
I tried most of the suggested answers, but what solved it was calling child.stdin.destroy();
child.stderr.destroy();
child.stdout.destroy();
This could be because I was explicitly using stdout to get data from the process..
I still call child.kill('SIGINT'); for good measure.
taskkill gave me 'pid not found'.
(node 12).

Run node as background process from script running as child process

I'm running a node server on port 5100. It executes a shell script as child process which in turn starts another node server.
var execFile = require('child_process').execFile;
execFile("./testscript", args, {cwd: cwd}, function (error, stdout, stderr) {
console.log("error.." + error);
console.log("stdout.." + stdout);
console.log("stderr.." + stderr);
})
In script i'm running a node process by nohup as :
nohup node server.js PORT=5200 2>/dev/null 1>/dev/null &
Now node#5200 has parentid of testscript which in turn has parentid of node#5100.
When i kill PID of node#5100 everything stops.
I want node#5200 to still run when testscript and node#5100 have exited.
You need to set the detached option when you create the child process. This is sort of like nohup. See the documentation here: http://nodejs.org/api/child_process.html#child_process_options_detached
What this does is to make the child process the leader of a new "process group," so when the parent process group dies, the child can continue running.
Edit: the documentation says:
When using the detached option to start a long-running process, the process will not stay running in the background unless it is provided with a stdio configuration that is not connected to the parent. If the parent's stdio is inherited, the child will remain attached to the controlling terminal.
So you must write code like this:
var child = spawn(cmd, args, {detached: true, stdio: ['ignore', 'ignore', 'ignore']});
child.unref();
Or you can use their example to have stdout redirect to a file, etc.
When i spawned a process from a file that ran once, my child process had perfect behavior as parent file exited normally.
Issue was raised as i was spawning process by a server file that was killed by Ctrl+c so it gave an error code on exit and as a result whole process group got SIGTERM which lead to killing of child process.
To successfully implement spawning i used double spawn i.e spawned a child process from my server file that further spawned child_process that ran my other node server. So i was able to avoid SIGTERM to reach grandchild and fulfill my requirement.

Why can I not kill my child process in nodejs on windows?

exec = require('child_process').exec;
child = exec('node child.js');
child.stdout.pipe(process.stdout);
child.kill('SIGKILL');
function wait() {
setTimeout(wait, 1000);
child.kill('SIGKILL');
}
wait();
The above code does not work. The child starts and will continue to write output indefinitely. I can not figure out how to kill this child process. I am running node v0.11.9 in Windows 7. I know that Windows does not use POSIX signals but sending it 'WM_QUIT' results in an exception. Is my best solution to setup an event protocol on stdin?
This still doesn't work for me with the current accepted answer. A work around on windows you can use is to call upon the windows taskkill program to kill the child process for you. Not quite as nice but it works. When you spawn the child you get a ProcessID (pid) stored in the child object returned when spawning, you can use with taskkill to kill the process.
var spawn = require('child_process').spawn;
spawn("taskkill", ["/pid", child.pid, '/f', '/t']);
I had to use the following package to kill my child process:
https://www.npmjs.com/package/tree-kill
The regular .kill command wouldn't work for me either on a raspberry pi.
If you want to be able to kill child processes via SIGKILL, use spawn instead, as spawn will create a child process (instead of a new shell like exec:
var exec = require('child_process').spawn;
Alternatively, you could pass the timeout parameter to exec, which will kill the process after that many milliseconds.
child = exec('node child.js', { timeout: 1000 });
Just an update
Now this code works (tested with Node.js 8.9.3 and Windows 10):
spawn = require('child_process').spawn;
child = spawn('node', ['child.js']);
setTimeout(function() {
child.kill();
}, 5000
);
check this code it worked for me.
var killer = require('child_process');
killer=exec('taskkill /F /pid '+child.pid);
Here killer is a variable and child is your child process.
when you create a child process it has many attributes associated with it and pid is one of them.
for more details on child process attributes and function check this node.js child process.
This program is to kill child process in windows environment.

Resources