我正在撰寫一個多執行緒程式,其中,我有一個執行緒偵聽傳入網路連接的套接字。為了允許這被中斷,我poll結合使用signalfd(而不是原始await呼叫)。但是,我還有其他執行緒需要能夠通知潛在的中斷,因此我sigwait在專用執行緒中使用呼叫來等待信號。我試圖讓比賽發生在下面的代碼中:
int main()
{
int sigval = 0;
sigset_t mask;
sigemptyset (&mask);
sigaddset (&mask, SIGINT);
pthread_sigmask(SIG_BLOCK, &mask, nullptr);
int sfd = signalfd(-1, &mask, SFD_NONBLOCK);
auto handler = std::thread([&] {
int signal;
sigwait(&mask, &signal);
sigval = signal;
});
pollfd pfd[1] = {{.fd=sfd, .events=POLLIN}};
int ret = poll(pfd, 1, -1);
std::cout << "Poll returned with revents = " << pfd[0].revents << std::endl;
handler.join();
std::cout << "Handled thread set sigval to: " << sigval << std::endl;
return 0;
}
每次我運行它并用 殺死它時SIGINT,它似乎都可以作業,因為poll呼叫回傳,sigval并由處理程式執行緒設定。但是,我的理解是sigwait消耗信號,而signalfd不會。因此,如果sigwait在signalfd收到信號通知之前以某種方式呼叫了該程式,則該程式可能會永遠掛起(輪詢等待未到來的信號)。我假設因為我無法讓程式掛起,所以引擎蓋下面有一些東西可以防止這種情況發生,但我能保證這永遠是真的嗎?
uj5u.com熱心網友回復:
我查看了 linux 源代碼,并對我自己的問題提出了一個答案:沒有競爭條件,因為在發送信號之前明確通知了 signalfd 觀察者,所以他們總是會在信號發出之前得到通知發送(并捕獲)。具體來說,在 中linux/kernel/signal.c,我們看到:
out_set:
signalfd_notify(t, sig); // <-- signalfd notified
sigaddset(&pending->signal, sig);
...
complete_signal(sig, t, type); // <-- sends the signal
所以sigwait在signalfd收到信號通知之前不可能消耗信號。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/388575.html
下一篇:兩個執行緒遞增一個數字
