2011-10-15 30 views
3

我正在編寫一個編程項目 - 在Python中編寫基本的P2P文件共享應用程序。我使用兩個線程:一個主線程調用select並等待來自套接字和sys.stdin列表的輸入(以接收輸入的命令)以及一個幫助線程,該狀態更新消息從隊列中取出並打印出來。 (它是唯一能夠打印任何內容的文件)Python中的信號處理程序的樂趣中斷選擇

我還需要捕獲標準的SIGINT並處理它以優雅地退出。我有一個戒菸的方法,這樣做,鍵入'quit'作爲一個命令工作得很好。所以在主線程中,我嘗試將此方法設置爲SIGINT的處理程序。據我所知,該進程捕獲信號並調用quit方法。輔助線程打印一條消息,確認它正在退出。但後來我從主線程得到以下錯誤信息:

Traceback (most recent call last): 
    File "peer.py", line 226, in <module> 
    main() 
    File "peer.py", line 223, in main 
    p.run() 
    File "peer.py", line 160, in run 
    readables, writables, exceptions = select(self.sockets, [], []) 
select.error: (4, 'Interrupted system call') 

之後程序仍然退出。鑑於沒有信號處理程序,發送SIGINT給我以下內容:

Traceback (most recent call last): 
    File "peer.py", line 225, in <module> 
    main() 
    File "peer.py", line 222, in main 
    p.run() 
    File "peer.py", line 159, in run 
    readables, writables, exceptions = select(self.sockets, [], []) 
KeyboardInterrupt 

無法終止程序;我必須制止並殺死它。這很令人困惑,因爲SIGINT似乎中斷了調用,只有當它被我的自定義方法捕獲時纔會選擇。 (其中只將消息放在打印隊列中並設置「完成」變量)有誰知道這會發生什麼?試圖同時使用信號處理程序和線程只是一個壞主意嗎?

+0

你能發表一小段代碼來重現這種行爲嗎? –

+0

是的,昨天晚上我停止工作後,我意識到我確實希望它中斷。據推測,它正在被執行信號處理程序中斷。所以我只是捕獲select.error並將其跳轉到循環的結尾,在那裏它立即退出並轉到清理代碼。 – dpitch40

+0

@ dpitch40,如果你已經回答了你的問題,你應該將該評論轉換爲答案並接受它。 –

回答

0

是的,昨晚我停止工作後,我意識到我確實希望它中斷。據推測,它正在被執行信號處理程序中斷。所以我只是捕獲select.error並將其跳轉到循環的結尾,在那裏它立即退出並轉到清理代碼。

0

我不知道如何使用信號處理程序捕獲這個情況,但我發現一個方法可以處理基於* nix系統這裏這種情況下:http://code.activestate.com/recipes/496735-workaround-for-missed-sigint-in-multithreaded-prog/

簡言之(如果我undertand正確) :

在您啓動任何新線程之前,請分叉子進程(使用os.fork)完成程序運行,並讓父進程監視KeyboardInterrupt

當父級捕獲鍵盤中斷時,可以使用os.kill殺死子進程(現在可能啓動了其他線程)。這將反過來終止該子進程的任何線程。

+0

除了捕捉信號的全部要點不僅僅是殺死程序,還要安全地停止它,關閉所有打開的連接。 – dpitch40

+0

這不會給你一個適當的方式/時間來做到這一點嗎? –