Bash script: can not properly handle SIGTSTP

2020-07-06 07:16发布

问题:

I have a bash script that mounts and unmounts a device, which performing some read operations in between. Since the device is very slow, the script takes about 15 seconds to complete (the mount taking atleast 5-6 seconds). Since leaving this device mounted can cause other problems, I don't want this script to be interrupted.

Having said that, I can correctly handle SIGINT (Ctrl+c), but when I try to handle SIGTSTP (Ctrl+z), the script freezes. Which means the signal is trapped but the handler doesn't run.

#!/bin/sh
cleanup()
{
    # Don't worry about unmounting yet. Just checking if trap works.
    echo "Quitting..." > /dev/tty
    exit 0
}
trap 'cleanup' SIGTSTP
...

I manually have to send the KILL signal to the process. Any idea why this is happening and how I can fix it?

回答1:

The shell does not execute the trap until the currently executing process terminates. (at least, that is the behavior of bash 3.00.15). If you send SIGINT via ^c, it is sent to all processes in the foreground process group; if the program currently executing receives it and terminates then bash can execute the trap. Similarly with SIGTSTP via ^z; bash receives the signal but does not execute the trap until the program that was being run terminates, which it does not do if it takes the default behavior and is suspended. Try replacing ... with a simple read f and note that the trap executes immediately.