Cronicle icon indicating copy to clipboard operation
Cronicle copied to clipboard

Aborting a job kills child, but leaves grand children alive

Open BernhardHH opened this issue 6 years ago • 3 comments

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

BernhardHH avatar Jul 11 '19 16:07 BernhardHH

+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?

fl4p avatar Aug 01 '19 06:08 fl4p

+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

atellier avatar Aug 29 '19 23:08 atellier

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

fl4p avatar Oct 08 '25 14:10 fl4p