Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Script called executed from bash script not handling signals

Tags:

python

bash

shell

Problem: When executing a python script from the command line, it catches and handles SIGTERM signals as expected. However, if the script is called from by a bash script, and then bash script then sends the signal to the python script, it does not handle the SIGTERM signal as expected.

The python script in question is extremely simple: it waits for a SIGTERM and then waits for a few seconds before exiting.

    #!/usr/bin/env python3

    import sys
    import signal
    import time


    # signal handler
    def sigterm_handler(signal, frame):
        time.sleep(5)
        print("dying")
        sys.exit()

    # register the signal handler
    signal.signal(signal.SIGTERM, sigterm_handler)


    while True:
        time.sleep(1)

If this is called directly and then the signal sent from the command line i.e.

> ./sigterm_tester.py &
> kill -15 <PID>

the signal handling performs normally (it waits 5 seconds, posts "dying" to stdout, and exits)

However, if it is instead called from a bash script, it no longer seems to catch the SIGTERM and instead exits immediately. This simple bash script executes the python script and then kills its child (the python script). However, the termination occurs immediately instead of after a 5 second delay, and there is no printing of "dying" to stdout (or to a file when I attempted stdout redirection).


    #!/bin/bash

    ./sigterm_tester.py &

    child=$(pgrep -P $$)

    kill -15 $child

    while true;
    do
        sleep 1
    done

Some additional information: I have also tested this with sh as well as bash and the same behavior occurs. Additionally I have tested this and gotten the same behavior in a MacOS environment as well as a Linux environment. I also tested it with both python2 and python3.

My question is why is the behavior different seemingly dependent on how the program is called, and is there a way to ensure that the python program appropriately handles signals even when called from a bash script?

like image 956
Matt Walck Avatar asked Sep 18 '25 21:09

Matt Walck


1 Answers

Summing @Matt Walck comments. In the bash script you were killing the python process right after invoking it, which might not had enough time to register on the sigterm signal. Adding a sleep command between the spawn and the kill command will back the theory up.

#!/bin/bash

./sigterm_tester.py &

child=$(pgrep -P $$)

#DEBUGONLY
sleep 2

kill -15 $child

while true;
do
        sleep 1
done
like image 75
Tomzan Avatar answered Sep 21 '25 12:09

Tomzan