Java nio 空轮询bug

这个应该是很老的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

你可能感兴趣的:(Java nio 空轮询bug)