2011-12-06 54 views
20

我一直在调试一个Python程序,它在收到KeyboardInterrupt异常后发生段错误。这通常通过从shell中按下Ctrl + C来完成。为了测试一个特定的代码修改是否修复了这个bug,我有一个小的shell脚本,它在启动后随机发送SIGINT到程序中。我遇到的问题是,发送Ctrl + C似乎对程序的影响不同于发送信号SIGINT并且因此不会导致错误出现,所以我很好奇这两个操作之间的区别是什么。Ctrl-C和SIGINT有什么区别?

该程序根本没有捕获到任何键盘动作,而只是一个包含一些线程/进程的Python程序。它没有安装信号处理程序(虽然Python),stty -a给出intr = ^C。我怀疑它可能是Ctrl + C发送SIGINT到所有的子进程/线程,而kill -INT只发送到主进程,但这是我的怀疑。

这里是发送kill -INT的shell脚本。

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 
+0

我不确定这会有多大的差异,但它可能ctrl + c发送'SIGTERM'而不是'SIGINT'。另外,处理异常时,你是否正确清理子流程/线程? python处理线程的方式我不相信它会出现seg-fault,但是它可能有子进程。 – David

+0

+ C可以配置,所以检查你的'stty -a'设置,寻找'intr =^C',也许^ C被设置为别的东西? – cdarke

+0

代码中是否有多线程? – Casey

回答

11

^C发送SIGINT到前台进程组中的所有进程。做kill等值金额,您应该将信号发送到进程组(OS层次的概念):

kill -SIGINT -<pid> 

或工作(壳层次的概念,管道与&结束):

kill -SIGINT % 
+0

这就是我一直在寻找的,但由于未知的原因,当我使用自动化脚本时,代码仍然没有段错误。我发现导致python崩溃的bug - python库多处理是用线程实现的,如果没有调用gobject.threads_init,它会在gobject中导致segfaults。尽管如此,对于我来说,最初的问题仍然是一个谜,因为手动调用ctrl + c触发了该错误,但自动脚本没有。 – Belorn

+2

不好意思,但是'%'在这方面意味着什么? –

+1

@KevinCantwell:它指的是当前的工作,即最后一次后台工作(在后台开始或在前台停止,因此后台停止)。 – ninjalj

4

作为described here

Python的默认安装少数信号处理程序:SIGPIPE 被忽略(所以写上管的错误和插座可报告为 普通的Python例外)和SIGINT被翻译成 KeyboardInterrupt异常。所有这些都可以被覆盖。

这样,行为应该发送SIGINT和Ctrl键 + Ç之间相同。

但是,你必须要小心与KeyboardInterrupt,如果一个地方在你的代码中有一个

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

这将“吃”的KeyboardInterrupt异常。

+0

感谢您的建议。发现有一行这样做,我认为这将修复一个无关的错误。但即使有这样的评论,segfault的主要问题仍然存在,发送kill -INT的更奇怪的一个不会触发它,但ctrl + c。 – Belorn