Aborting a job kills child, but leaves grand children alive
Summary: Aborting jobs kills the child process, but not any forked grand childs.
process.on('SIGTERM', function() {
console.log("Caught SIGTERM, killing child: " + child.pid);
kill_timer = setTimeout( function() {
// child didn't die, kill with prejudice
console.log("Child did not exit, killing harder: " + child.pid);
child.kill('SIGKILL');
}, 9 * 1000 );
// try killing nicely first
child.kill('SIGTERM');
} );
This might or might not be on purpose - but it would be great to have the option to clean up all the childs of an aborted job.
I would propose finding all the processes which have the child.pid as parent PID, sigterm/kill them first, then sigterm/kill the child.
Killing the PGID is not a solution, because that kills the node process, too :)
Cheers, Bernhard
+1
I currently use three methods to prevent "zombie" orphan child processes:
- Frequently list all processes with PPID==1 and kill those matching an expression
- In all child proccesses frequently check if PPID == 1 and terminate
- Implement a recursive kill function in the Cronicle plugin that traverses through the process branch
Althoug the first 2 seem to be quite realiable, these are all hackish solution.
Does anyone know how systemd solves this?
+1
Would love to have a clean solution to that too... I am using the Shell Script plugin to run another script, and unfortunately the process is left behind on abort:
#!/bin/bash
/opt/run_internal_job.sh my_job_here
run_internal_job.sh sets up virtualenv and run a python script... that does not get kill on abort.
Thanks
This still hasn't been fixed, so here's my script I run every 5 minutes to kill all matching zombies:
#!/usr/bin/env zsh
descendants(){
echo $1
pgrep -P $1 | while read -r c; do descendants $c; done
}
killnoerr() {
kill -9 $1 > /dev/null 2> /dev/null || :
}
killbranch() {
echo "killbranch $(ps -fp $1 | tail -n 1)"
descendants $1 | while read -r p; do killnoerr $p; done
}
killmatches() {
awk '{print $1}' | while read -r p; do killbranch $p; done
}
for ((i = 0; i < 4; i++)); do
echo "pgrep..."
pp1=`pgrep -a -P 1`
echo $pp1 | grep -a "myprocessname1" | grep -a "additional cmd line filter" | killmatches
echo $pp1 | grep -a "myprocessname2" | grep -a "additional cmd line filter" | killmatches
done;
You need to adjust the grep filter (myprocessname1), it is needed so it doesn't kill any system processes