2013-11-26 254 views
1

我正在使用多線程嵌入式應用程序,其中epoll在其中一個線程中用於IO。我依賴epoll的一個特殊功能,它指定關閉一個文件描述符會自動將它從epoll集中移除(man 7 epoll中的Question/Answer 6)。在這種情況下,文件描述符關閉在調用epoll_wait的同一個線程中完成。結果發生的是epoll_wait在關閉文件描述符後返回一個事件,並且程序最終崩潰,因爲它試圖訪問當文件描述符關閉時解除分配的資源。據我所知,文件描述符在任何地方都沒有,儘管我不知道如何驗證它。我知道有一個事實,即沒有撥打fork()dup(),dup2()fcntl()與特定的dup選項。這個特定的文件描述符是用EPOLLOUT,EPOLLIN,EPOLLERREPOLLHUP登記的。它是電平觸發的。有沒有人知道這個功能的任何警告?手冊頁是否有誤?任何有用的信息可以幫助我進一步調試該問題?我知道我可以從集合中刪除文件描述符,但我想知道爲什麼會發生這種情況。Epoll_wait在關閉的文件描述符上返回事件

+0

epoll_wait爲該文件描述符返回的事件是EPOLLIN,EPOLLHUP和EPOLLERR。 – duffsterlp

+0

您可以使用[strace](http://linux.die.net/man/1/strace)來驗證您的程序是否在執行您認爲正在執行的操作。你能在一個簡單的單線程測試程序中重現這種行爲嗎? –

回答

2

關閉一個文件描述符似乎並沒有將它從epoll中移除。我在3.12.2上用一個非常簡單的例子試了一下。我傾向於將該手冊頁稱爲錯誤或不準確。

我在測試做了什麼:

  • 創建TCP套接字
  • 束縛,爲localhost:5555
  • 設置它來聽
  • 創建了一個epoll的
  • 添加的插座有hup,err和
  • 睡了一下,所以我可以選擇使用nc連接
  • 關閉套接字
  • epoll_wait
  • epoll_ctl德爾
  • 清理

等待工作,即使插座已被關閉我是否已經連接到這一點。

編輯:The epoll_ctl_del如果套接字已關閉,則確實失敗。在閱讀了當前的手冊頁之後,看起來他們確實沒問題。 epoll頁面指向選擇(2)關於關閉被監視的套接字,並且該頁面表示行爲未指定。

+0

爲了記錄,我在一個服務器上做了什麼,當一個連接被關閉時,我明確地將它從epoll中刪除(並且實際上標記了epoll以重新等待它剛剛從epoll_wait中出來,這是運行在另一個線程),然後繼續關閉並銷燬相關資源。 –

+0

epoll_ctl del在你的例子中工作的事實是高度可疑的。套接字未關閉或者已被複制。我們可以看到代碼嗎? –

+0

找到了代碼。果然,'epoll_ctl_del'確實失敗了。我爲我的測試程序製作了「doclose」標誌,以檢查epoll等待返回值是否在關閉套接字的情況下進行,並且我必須在沒有關閉的情況下從運行中獲取「del工作」,當然它的工作原理。 –