2016-10-02 64 views
0

我有SIGINT處理程序。它爲整個程序設置變量:errflag。當我做select(),它通過SIGINT中斷,我檢查errflag,看看它是否是SIGINT(有自己的常數分配到errflag)。但是,處理程序可能會晚,errflag尚未設置。如何在處理程序的errflag解決方案之前推遲處理?或者如何正確實施?如何確保信號處理程序完成,然後才繼續程序?

此外,在一個代碼路徑select()返回-1上Ctrl-C鍵,errnoEINTR。這裏處理程序永遠不會遲到在其他路徑select()返回-1,errno也是EINTR,但處理程序稍後輸出日誌消息並且遲到,我的errflag檢查已經執行。

+0

正如第一個答案中指出的那樣,中斷會停止當前處理並運行處理程序,如果處理程序返回,則重新啓動系統調用或將errno設置爲EINTR來中斷它。你使用'signal()'還是'sigaction()'?如果沒有你的代碼,很難看到發生了什麼問題,但是你的解釋是信號處理程序可以被「推遲」,這基本上是錯誤的。使用'sigaction()',您可以在處理另一個信號'sa_mask'時阻塞一個信號,但當第一個處理程序返回時將阻止信號。 –

+0

@JonathanLeffler:你是對的,信號是通過隊列機制手動延遲的,並且處理程序提前返回,在此之前沒有調試打印,並將來自隊列的調用解釋爲第一個,最後一個調用。 – Itzie

+0

所以,你有一個信號處理器有兩個或更多的退出路線,一個有診斷打印,另一個沒有?輕鬆完成 - 但也需要注意。這可能導致對結果的嚴重誤解。 「單次進入,單次退出」編程的(少數)優點之一就是你不會遇到這個問題! –

回答

3

但是,處理程序可能晚,errflag尚未設置。

呃,什麼?不,它不能「遲到」。這裏還有其他的錯誤。

信號處理程序中斷正常的程序流程 - 當接收到SIGINT時,處理程序運行,並且控制流程僅在信號處理程序退出時釋放到程序的其餘部分。

您需要確保的是errflag被聲明爲volatile,以便編譯器不會對其值可能更改的時間做出過分的假設。

您還需要記住的是printf()在信號處理程序中使用不安全,因爲它可能使用全局緩衝區,在信號處理過程中可能會保持不一致的狀態。 Generally speaking, very few things are safe to do during a signal handler besides setting volatile global variables or exiting.嘗試在信號處理程序中使用printf()可能會導致不一致的混淆結果;輸出不應該被用作程序中實際發生的事情的可靠指標!

+0

謝謝,我已經驗證過,並且處理程序立即被調用,只有排隊機制,稍後再次從隊列中再次觸發信號。稍後,在可能的排隊之後,我有調試消息,並且沒有看到即時的on-signal處理程序調用。 – Itzie