為什麼有必要在 sigwait()‘ing 之前阻止信號?
在 APUE 第 12 章第 454 頁中,提到:
為了避免錯誤行為,執行緒必須阻塞它正在等待的信號……
標準中也有類似的說法:
set定義的信號在呼叫*sigwait()*時應該被阻塞;否則,行為未定義。
這些文本中討論了哪些錯誤/未定義的行為?我在標準中找不到基本原理或應用程序用法,而且我很難理解書中的解釋:
如果信號沒有被阻塞……,則打開一個計時視窗,其中一個信號可以線上程完成對
sigwait
.
這個答案首先將讀者帶到標準制定的歷史視角,然後將讀者的注意力引向標準的具體文本,以解釋要求的原因。
在 XPG 第 3 期中,引入
sigaction
了sig*set
、sigismember
、sigpending
、sigprocmask
、 和sigsuspend
,以符合 POSIX.1-1988 標準。其中,sigaction
為指定信號配置提供了最全面和一致的介面;sigpending
,sigprocmask
並sigsuspend
提供了對信號進行細粒度響應的方法。在 XPG 第 4 期(目前最古老的數字形式)中,
sigaltstack
引入了、sig{hold,ignore,pause,relse,set}
、 。siginterrupt
最新的標準沒有說明它們來自哪裡,只是說它們都sigaltstack
已經過時了,因為它們只在單執行緒程序中工作。在 XPG 第 5 期(單一 Unix 規範版本 2)中,引入了
pthread_sigmask
,sigqueue
,sigtimedwait
,sigwaitinfo
, 並sigwait
與 POSIX 實時和執行緒擴展保持一致。現在,看看標準中的其他兩個地方很重要。
系統介面一般資訊卷第一名,信號概念:
…可以“阻止”信號傳遞到執行緒。如果與阻塞信號相關聯的動作不是忽略該信號,並且如果該信號是為執行緒生成的,則該信號應保持掛起直到它被解除阻塞,當它被選擇並通過呼叫返回時被接受
sigwait()
函式或與之關聯的動作被設置為忽略信號。顯然,除了可能最終忽略信號外,信號還有兩種到達程序/執行緒的方式——被解除阻塞,或被
sigwait
(及其兄弟姐妹,如sigtimedwait
andsigwaitinfo
)接受第二名
sigaction
:未指定在同一信號的程序內同時使用 sigaction() 和 sigwait() 函式的結果。
顯然,
sigwait
已被設想為處理信號的次要方法。
sigtimedwait
和sigwaitinfo
介面的基本原理中的以下文本進一步證實了這一點:sigwait 函式為執行緒提供了一種同步機制來等待非同步生成的信號。
這來自qnx 文件,但它與所有 Unix 和類似 Unix 的發行版相關:
在呼叫 sigwait() 之前,應該阻止 set 定義的信號。如果您不阻止它們,則會出現競爭條件,即可以在發出呼叫之前傳遞信號,從而導致呼叫被阻止,您可能不希望它這樣做。