2013-01-09 103 views
1

這是繼續問題14221339.epoll是否有線程安全問題?

我有一個在epoll_wait()循環內運行的線程池。

外部線程調用epoll_ctl(),並增加了與

(EPOLLET | EPOLLONESHOT | EPOLLIN)一個監聽套接字。

當線程池只有一個線程時,它間歇性地無法接收第一個(也是唯一)連接嘗試的EPOLLIN事件。如果我將線程池增加到兩個,它幾乎總是無法收到EPOLLIN事件。

我的理解是,epoll API是線程安全的,但是這個觀察似乎表明了其他情況。

回答

5

使用邊緣觸發的語義,不正確的調用序列可能會導致競爭條件。有三個系統調用涉及:

  1. epoll_ctl()以激活通知(並且如果使用 EPOLLONESHOT激活)。
  2. epoll_wait()接收通知。
  3. 系統輸入:在循環中讀取()/ recv()/ accept(),直到錯誤EAGAIN。

如果以該順序執行(重複),則#3和#1之間的競爭是可能的:當內核中的輸入事件發生在EAGAIN已被返回但可以對epoll_ctl()執行操作之前。通常,重新激活需要在I/O之前完成。

  1. epoll_ctl()以激活通知(並且如果使用 EPOLLONESHOT重新激活)。
  2. 系統輸入:在循環中讀取()/ recv()/ accept(),直到錯誤EAGAIN。
  3. epoll_wait()接收通知。

(顯然,I/O需求是不可阻擋。)

+1

我發現這個問題,它實際上已經無關epoll的。我的應用程序是用C++編寫的,線程池的創建包含一個帶有可變參數和std :: bind的遞歸模板函數。發生了一些奇怪的競態條件,其中std :: function對象被清除,所以線程永遠不會進入epoll_wait()循環。 – user1715664

+1

很高興你解決了這個問題! – arayq2

+0

@ arayq2你確定該電話訂單嗎?我從來沒有看到任何epoll相關的順序調用它們?我有一個類似的問題[這裏](http://stackoverflow.com/questions/33885439/epoll-with-edge-triggered-and-oneshot-only-reports-once)。手冊頁建議,一旦fd被重新啓用,如果它能夠符合標誌的標準,即使在等待之後調用ctl,它也會觸發事件。任何額外的信息,你可以給這個將是偉大的:) – nathansizemore