2012-10-23 96 views
3

在Ruby中,我清楚地知道,最近註冊的信號捕集器的一個優先,使:紅寶石信號捕手優先

Signal.trap("TERM") {puts "foo"; exit} 
Signal.trap("TERM") {puts "bar"; exit} 

如果我發出「殺」以上腳本,它會打印出「酒吧」並退出。

有沒有一種方法,在Ruby本身,爲trappers強制執行某種範圍?

我的具體情況是這樣的:

我們有一個定義了自己的捕獸的應用程序(這個故事,我們只能說這只是陷阱「期限」)的命名空間的信號模塊。該代碼在運行時需要進入應用程序,並且在此之後幾乎不做任何處理。

第三方寶石(我不會指名道姓),我們使用,在初始化方法「術語」 實際上註冊了自己的捕手,所以最近初始化的對象將是一個處理「 TERM「信號,結果不理想......

儘管第三方gems的對象可能有自己的trappers定義,但我不希望它們影響我的應用程序。

有人知道有一種方法可以讓非初始化非非第三方的捕捉器優先順序變得太花哨嗎?

+2

這聽起來像是第三方gem中的一個壞bug ......如果它有多個對象會發生什麼?它是否有一些調用所有活動對象的處理程序的方法? – nneonneo

+0

它的確如此,但它與信號捕獲無關,因爲給定信號的最新註冊捕獲器將是Ruby始終用於該信號的捕獲器。我不確定這是Ruby的默認行爲,還是可配置或什麼。 (雖然我同意它可能不是第三方寶石中的理想行爲) –

回答

3

你可以猴子補丁Signal別名Signal.trap,然後用無操作替換:

module Signal 
    class << self 
     alias_method :real_trap, :trap 
     def trap(*) end 
    end 
end 

然後你就可以在你的代碼和你使用會被忽略這個粗魯的不願透露姓名的寶石使用real_trap。你必須確保Signal已經在你的粗魯寶石做任何事之前進行了修補。

有了這個補丁,發送SIGTERM這個代碼:

Signal.trap("TERM") {puts "foo"; exit} 
Signal.trap("TERM") {puts "bar"; exit} 
Signal.real_trap("TERM") {puts "pancakes"; exit} 

會給你的煎餅。

我通常會盡量避免使用猴子修補程序,但它對於糾正錯誤和其他不良行爲是非常有用的。

+3

或者是猴子補丁或叉子寶石。 –

+0

@Andrew:這也是一個選項,取決於'Signal.trap'調用周圍有多少東西。 –

+0

我其實並沒有考慮猴子補丁Signal,但我希望完全避免猴子補丁。這看起來像我不得不爲這個特定問題破壞。我將爲有問題的寶石提供一個補丁(在我看到的幾年內它沒有被觸及,所以最終可能會分叉)。我會留下這個開放一段時間,看看是否有其他人有什麼要說的,如果沒有,答案是你的@ muistooshort –