2

When trapping a signal in a shell script, the trap commands are not executed until the current command finishes. For example, consider the following shell script:

#!/bin/bash

trap 'echo "SIGTERM caught"' SIGTERM

i=0
while : ; do
  echo "$((++i))"
  timeout 10 yes >/dev/null
done

If one runs this script and then tries to send SIGTERM to the process, the echo statement in the trap function does not run until completion of the active command.

By backgrounding a command and using wait, signals can be handled during command execution, e.g.,

#!/bin/bash

trap 'echo "SIGTERM caught"; [[ "$pid" ]] && echo "Killing $pid" && kill "$pid"' SIGTERM

i=0
while : ; do
  echo "$((++i))"
  timeout 10 yes >/dev/null &
  pid=$!
  wait
done

However, while SIGTERM is now caught immediately, this causes the process to respond incorrectly to other signals like SIGINT. For instance, if the above script is run, it cannot be terminated by SIGINT if SIGTERM was sent more than a few moments earlier. For instance, if $pid is the process ID of the shell script, either of the following will kill the process (in the latter case, the process is interrupted by SIGINT before it has a chance to respond to SIGTERM):

kill -SIGINT "$pid"
kill "$pid"; kill -SIGINT "$pid"

whereas the following will not (the process hangs and must be killed by delivering SIGKILL):

kill "$pid"; sleep 0.01; kill -SIGINT "$pid"
SIGTERM caught
# process hangs at this point

What changes need to be made to the trap to avoid improper handling of other signals?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.