![](/img/trans.png)
[英]Is there a full memory barrier around sem_post(sem_t * sem) and sem_wait(sem_t * sem)?
[英]Signal safe use of sem_wait()/sem_post()
我試圖在Linux上創建一個包裝器,它控制一次允許多少次並發執行。 為此,我使用系統范圍的計數信號量。 我創建信號量,執行sem_wait()
,啟動子進程,然后在子進程終止時執行sem_post()
。 那樣就好。
問題是如何安全地處理發送給這個包裝器的信號。 如果它沒有捕獲信號,則命令可能會在不執行sem_post()
情況下終止,從而導致信號量計數永久減少1。 所以,我創建了一個執行sem_post()
的信號處理程序。 但是,仍有一個問題。
如果在執行sem_wait()
之前附加了處理程序,則信號可能在sem_wait()
完成之前到達,從而導致sem_post()
在沒有sem_wait()
情況下發生。 如果我在設置信號處理程序之前執行sem_wait()
,則可以sem_wait()
。
顯而易見的下一步是在處理程序和sem_wait()
的設置期間阻止信號。 這是我現在擁有的偽代碼:
void handler(int sig)
{
sem_post(sem);
exit(1);
}
...
sigprocmask(...); /* Block signals */
sigaction(...); /* Set signal handler */
sem_wait(sem);
sigprocmask(...); /* Unblock signals */
RunChild();
sem_post(sem);
exit(0);
現在的問題是sem_wait()
可以阻塞,在此期間,信號被阻塞。 試圖殺死進程的用戶可能最終訴諸“kill -9”,這是我不想鼓勵的行為,因為無論如何我都無法處理這種情況。 我可以使用sem_trywait()
一小段時間並測試sigpending()
但這會影響公平性,因為不再保證等待信號量最長的進程將在下一次運行。
這里有一個真正安全的解決方案,允許我在信號量采集期間處理信號嗎? 我正在考慮求助於“我有信號量”全局並消除信號阻塞,但這不是100%安全,因為獲取信號量並設置全局不是原子的,但可能比等待時阻塞信號更好。
你確定sem_wait()
導致信號被阻止嗎? 我不認為是這種情況。 sem_wait()
的手冊頁說如果它被信號中斷,則從sem_wait()
返回EINTR
錯誤代碼。
您應該能夠處理此錯誤代碼,然后您的信號將被接收。 您是否遇到未收到信號的情況?
我會確保你處理sem_wait()
可以返回的錯誤代碼。 雖然可能很少見,但如果你想100%確定你想要100%的基數。
我知道這已經過時了,但為了那些仍在閱讀Google禮貌的人的利益......
這個問題的最簡單(也是唯一的)穩健解決方案是使用System V信號量,它允許客戶端以一種內核自動返回的方式獲取信號量資源。無論過程如何排除。
你確定你正確地接近了這個問題嗎? 如果要等待子進程終止,可能需要使用waitpid()
系統調用。 正如您所觀察到的,如果孩子可能接收到信號,那么期望孩子做sem_post()
是不可靠的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.