Java nio 空輪詢bug

王春浩troy發表於2019-01-19

這個應該是很老的bug了,linux平臺,jdk6好像就修復了

bug 描述 :https://bugs.java.com/bugdata…

This is an issue with poll (and epoll) on Linux. If a file descriptor for a connected socket is polled with a request event mask of 0, and if the connection is abruptly terminated (RST) then the poll wakes up with the POLLHUP (and maybe POLLERR) bit set in the returned event set. The implication of this behaviour is that Selector will wakeup and as the interest set for the SocketChannel is 0 it means there aren`t any selected events and the select method returns 0.

之前一直不知道event mask 為0 代表啥,知道翻到了資料

http://man7.org/linux/man-pag…

The field events is an input parameter, a bit mask specifying the
events the application is interested in for the file descriptor fd.
This field may be specified as zero, in which case the only events
that can be returned in revents are POLLHUP, POLLERR, and POLLNVAL
(see below).

大概知道了0代表了POLLHUP, POLLERR, and POLLNVA 這些event

繼續查閱https://blog.csdn.net/tilter/…

常量 說明
POLLIN 普通或優先順序帶資料可讀
POLLRDNORM 普通資料可讀
POLLRDBAND 優先順序帶資料可讀
POLLPRI 高優先順序資料可讀
POLLOUT 普通資料可寫
POLLWRNORM 普通資料可寫
POLLWRBAND 優先順序帶資料可寫
POLLERR 發生錯誤
POLLHUP 對方描述符掛起
POLLNVAL 描述字不是一個開啟的檔案

大概明白了Bug描述中 abruptly terminated (RST)的含義及發生場景

也就知道什麼時候會發生空輪詢bug

個人記錄下


還有1問題沒想明白,為啥先cancel,再select(or selectNow) 還是無法避免這個問題? ref: https://www.cnblogs.com/JAYIT…
網上說,在多執行緒環境下,selectNow先發生,cancel後發生,這樣還是會存在問題
但是,即使cancel後發生,channel也會被移到待移除channel集合了,下次再輪詢的時候,select也會出發這個集合裡面的channel被清除
這樣,最多多一次空輪訓。
目前給的方案都是open一個新的selector,把有效的channel全部註冊到新的selector,再輪詢新的selector