Category Archives: Renderfarming

Terminating a child process from python

fixing a problem with calling 3rd party applications as subprocesses

I’ve been working on improving my renderfarm, and I’ve run into some trouble trying to close clients remotely. You can easily end a python process with sys.exit(), however if a rendering application (say Nuke) has been spawned by the script, it will not close. After some digging (and a bunch of great help from stackOverflow) I seem to have come up with a solution. When you call a 3rd party application with either call() or:

process = Popen(allRenderArg, env=os.environ)

Python will create a tiny, dummy process which only exists to call that application. When you exit your script, python will clean up those dummy processes, but won’t kill child processes, thereby leaving the renders going.

The solution that I’ve come up with is to get the pid of those dummy python processes, then use some unix commands to find the pids of their children, and kill them with os.kill(). If this was a linux platform I could do it in a more efficient way (possibly using pstree) but on OSX I have to use grep and some fancy code:

processId = process.pid
print "attempting to terminate "+str(processId)
command = " ps -o pid,ppid -ax | grep "+str(processId)+" | cut -f 1 -d \" \" | tail -1"
ps_command = Popen(command, shell=True, stdout=PIPE)
ps_output = ps_command.stdout.read()
retcode = ps_command.wait()
assert retcode == 0, "ps command returned %d" % retcode
print "child process pid: "+ str(ps_output)
os.kill(int(ps_output), signal.SIGTERM)
os.kill(int(processId), signal.SIGTERM)

There might be a nicer way, but I don’t know it.