What is the difference between Ctrl-C and SIGINT?

2019-02-02 04:46发布

I have been debugging a Python program which segfaults after receiving a KeyboardInterrupt exception. This is normally done by pressing Ctrl+C from the shell. To test if a particular code change fixed the bug, I had a small shell-script that sent SIGINT to the program at random time after start-up. The problem I have is that sending Ctrl+C seems to have a different effect on the program than sending the signal SIGINT and is thus not causing the bug to appear, so I quite wonder what the difference is then between the two actions.

The program does not catch any keyboard actions at all, and is just a python program with some threads/processes in them. It installs no signal handlers (though Python does), and stty -a gives intr = ^C. I suspect it might be that Ctrl+C sends SIGINT to all the sub-processes/threads while kill -INT only sends to the primary process, but that is as far my suspicions go.

Here is the shell script which sends the kill -INT.

wait
while :; do
    seconds="$(python -c 'import random; print random.random()*4')"
    ./mandos --debug --configdir=confdir \
             --statedir=statedir --no-restore --no-dbus &
    pid=$!
    { sleep $seconds; kill -INT $pid; } &
    fg %./mandos
    status=$?
    if [ $status -gt 1 ]; then
        echo "Failed exit $status after $seconds seconds"
        break
    fi
    wait
done

2条回答
男人必须洒脱
2楼-- · 2019-02-02 05:16

^C sends a SIGINT to all the processes in the foreground process group. To do the equivalent with kill, you should send the signal to the process group (OS-level concept):

kill -SIGINT -<pid>

or to the job (shell-level concept, the pipeline ended with &):

kill -SIGINT %
查看更多
Lonely孤独者°
3楼-- · 2019-02-02 05:30

As described here :

Python installs a small number of signal handlers by default: SIGPIPE is ignored (so write errors on pipes and sockets can be reported as ordinary Python exceptions) and SIGINT is translated into a KeyboardInterrupt exception. All of these can be overridden.

so, the behaviour should be the same between sending a SIGINT and a Ctrl + c.

But, you have to be carefull with the KeyboardInterrupt, if somewhere in your code you've got a

try:
   ...
except:   # notice the lack of exception class
   pass

this will "eat" the KeyboardInterrupt exception.

查看更多
登录 后发表回答