2009-11-02 51 views
7

由於某些原因,siginterrupt()似乎只能設置接收到的第一個信號的行爲。siginterrupt()僅適用於第一個信號? (Python)

在此示例程序中,第一個SIGQUIT看起來什麼都不做,但第二個sigquit打印出「SIGQUIT Handler」,而s.accept()則拋出了Interrupted系統調用異常。

from signal import * 
from socket import * 
import sys 

def sigquitHandler(signum, frame): 
     print("SIGQUIT Handler") 

s = socket() 
s.bind(("0.0.0.0", int(sys.argv[1]))) 
s.listen(5) 

signal(SIGQUIT, sigquitHandler) 
siginterrupt(SIGQUIT, False) 

client, addr = s.accept() # Or any syscall that blocks 
client.close() 
s.close() 

我在這裏誤解了什麼?


編輯:這是別的東西,我不明白,在這個程序中,一個SIGQUIT中斷select()。這是否應該發生?

from signal import * 
import select 
import sys 

def sigquitHandler(signum, frame): 
    print("SIGQUIT Handler") 

signal(SIGQUIT, sigquitHandler) 
siginterrupt(SIGQUIT, False) 

select.select([sys.stdin], [], []) 
+1

我認爲'siginterrupt'真的只適用於涉及數據(原語如打開,讀取或寫入)的傳輸系統調用。我不認爲它適用於像「select」這樣的系統調用。 – mhawke 2009-11-03 04:19:05

+0

啊,好的。再次感謝:) – 2009-11-03 05:09:51

回答

2

您使用哪個unix?在C級別,BSD和System 5(SYSV)上的信號處理有不同的實現和語義。

我的猜測是你正在使用SYSV,在這種情況下,在信號處理程序返回(經典信號處理)後,信號處理被重置爲SIG_DFL。在SYSV上,您需要在處理程序中調用signal以重新安裝該處理程序。

Python或多或少的提供了BSD風格的信號處理。因此,在SYSV OS上,Python必須通過signal來管理信號處理程序的重新安裝。現在,根據Python的DOCO爲siginterrupt

注意,在安裝與信號(信號處理程序 )由 隱式調用siginterrupt()與 爲一個真正的標誌值將復位重啓 行爲中斷給出 信號。

而且你去那裏 - 如果 Python是自動重新安裝信號處理器(提供BSD類似語義),很可能在隱式調用siginterrupt(1)的方式這樣做。

當然,我的猜測可能是錯的。

可能可以通過定義sigquitHandler這樣來解決這個問題:

def sigquitHandler(signum, frame): 
    print("SIGQUIT Handler") 
    siginterrupt(SIGQUIT, False) 

這取決於何時以及如何Python是恢復信號的配置上。

編輯

添加siginterrupt(SIGQUIT, False)到信號處理程序沒有影響。

EDIT 2

後一些閒逛的python2.6的源代碼清楚,這不只是一個SYSV問題。它也會影響BSD系統。

+0

這很有道理,謝謝! – 2009-11-03 02:56:50

4

這是一個python的bug。「siginterrupt with flag = False在接收到信號時重置」,這在後面的python2.6版本中已經修復。 (2.6.6+,2.7+)

對於第二個,siginterrupt不影響select()。

看到http://lkml.org/lkml/2005/7/23/119

相關問題