Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python - terminate child process when script invoked from bash

I have a python script: zombie.py

from multiprocessing import Process
from time import sleep
import atexit

def foo():
    while True:
        sleep(10)

@atexit.register
def stop_foo():
    p.terminate()
    p.join()

if __name__ == '__main__':
    p = Process(target=foo)
    p.start()

    while True:
        sleep(10)

When I run this with python zombie.py & and kill the parent process with kill -2, the stop() is correctly called and both processes terminate.

Now, suppose I have a bash script zombie.sh:

#!/bin/sh

python zombie.py &

echo "done"

And I run ./zombie.sh from the command line.

Now, stop() never gets called when the parent gets killed. If I run kill -2 on the parent process, nothing happens. kill -15 or kill -9 both just kill the parent process, but not the child:

[foo@bar ~]$ ./zombie.sh 
done
[foo@bar ~]$ ps -ef | grep zombie | grep -v grep
foo 27220     1  0 17:57 pts/3    00:00:00 python zombie.py
foo 27221 27220  0 17:57 pts/3    00:00:00 python zombie.py
[foo@bar ~]$ kill -2 27220
[foo@bar ~]$ ps -ef | grep zombie | grep -v grep
foo 27220     1  0 17:57 pts/3    00:00:00 python zombie.py
foo 27221 27220  0 17:57 pts/3    00:00:00 python zombie.py
[foo@bar ~]$ kill 27220
[foo@bar ~]$ ps -ef | grep zombie | grep -v grep
foo 27221     1  0 17:57 pts/3    00:00:00 python zombie.py

What is going on here? How can I make sure the child process dies with the parent?

like image 367
user545424 Avatar asked Jan 23 '26 14:01

user545424


1 Answers

Neither the atexit nor the p.daemon = True will truely ensure that the child process will die with the father. Receiving a SIGTERM will not trigger the atexit routines.

To make sure the child gets killed upon its father's death you will have to install a signal handler in the father. This way you can react on most signals (SIGQUIT, SIGINT, SIGHUP, SIGTERM, ...) but not on SIGKILL; there simply is no way to react on that signal from within the process which receives it.

Install a signal handler for all useful signals and in that handler kill the child process.

like image 166
Alfe Avatar answered Jan 25 '26 03:01

Alfe