开发者

How do I trap SIGQUIT properly in a bash script?

I can write shell scripts that trap SIGINT just fine, but I can't seem to trap SIGQUIT.

#!/bin/bash

function die {
    echo "Dying on signal $1"
    exit 0
}

trap 'die "SIGINT"' SIGINT
trap 'die "SIGQUIT"' SIGQUIT

while true; do
    echo "sleeping..."
    sleep 5
done

Executing this script and pressing CTRL-C has the desired effect, but pressing CTRL-\ (which, as I understand, should trigger SIGQUIT) does nothing except print ^\ in the terminal. Why?

I have two running theories. The first is that the semantics of SIGINT and SIGQUIT are different such that SIGQUIT only gets sent to the child process sleep, while SIGINT gets sent to both the child process and the parent bash process. If this is the case, where is it documented?

My second theory is that bash not only ignores (i.e., has a no-op handler for) SIGQUIT by default (as the man page suggests), but does not allow it to be trapped at all. This theory overlaps with the first theory, since it could be the case that SIGQUIT is going to both parent and child, but the parent (bash) just can't trap it. If this is the case, is there any way to trap SIGQUIT in a bash script?... perhaps some shopt I can set?

Edit: this is on Ubuntu 10.10 in gnome-terminal 2.32.0 running bash 4.1.5, and yes ^\ is configured to issue SIGQUIT (as reported by stty -a and confirmed by issuing ^\ SIGQUITs to other programs like ping).

UPDATE: I just discovered that the problem must be due somehow to gnome-terminal. If I run this script from a virtual console (i.e., ctrl-alt-f1 to get out of X), it traps SIGQUIT perfectly fine when I press ^\. Same bash and everything, so the only difference must be t开发者_如何学Gohe terminal emulator. So now my question becomes: how can I configure gnome-terminal to behave like the virtual console in this respect? I diff'd the outputs of stty -a in the virtual console and in gnome-terminal, and while there are differences, nothing seems immediately relevant (e.g., they both have quit = ^\;).

UPDATE 2: Another experiment. Simply execute $ sleep 60 in gnome-terminal; press ^\ and the signal goes uncaught. Now execute $ sleep 60 in the virtual console; press ^\ and the signal is caught -- the process prints Quit and exits. But now run $ ping google.com in gnome-terminal and press ^\ -- the signal is caught and handled as expected. So there is something weird about gnome-terminal such that SIGQUIT can be caught by some programs, but not by others, even if those other others do catch it when invoked from the virtual console. Perhaps I should just upgrade my gnome-terminal.


I can only assume that this was some sort of bug in gnome-terminal 2.32.0; I have since upgraded to Ubuntu 11.04, with gnome-terminal 2.32.1 (and bash 4.2.8) and SIGQUIT is now trapped as expected.


I observe the same behavior on Fedora 19 with XFCE: according to ps s, bash in the xfce4-terminal has SIGQUIT ignored, running yes >/dev/null & and then ps s shows that even a subprocess has SIGQUIT ignored. When I (from the same terminal) run ssh localhost, the shell in the ssh session also has SIGQUIT ignored, but yes >/dev/null & has not.

Given the above comment which mentions gnome-terminal, I would guess the bug is in the common part of the two terminals: the vte library. Mine is vte-0.28.2-9.fc19.x86_64.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜