2011-12-06 58 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