EPOLL事件之EPOLLRDHUP

来源:互联网 发布:安徒生童话 知乎 编辑:程序博客网 时间:2024/05/14 07:10

在对系统问题进行排查时,我发现了一个奇怪的现象:明明是对方断开连接,系统却报告一个查询失败的错误,但从用户角度来看请求的结果正常返回,没有任何问题。

对这个现象深入分析后发现,这是一个基于epoll的连接池实现上的问题,或者说是特性。

首先解释一下导致这个现象的原因。

在使用epoll时,对端正常断开连接(调用close()),在服务器端会触发一个epoll事件。在低于2.6.17版本的内核中,这个epoll事件一般是EPOLLIN,即0x1表示连接可读。

连接池检测到某个连接发生EPOLLIN事件且没有错误后,会认为有请求到来,将连接交给上层进行处理。这样以来,上层尝试在对端已经close()的连接上读取请求,只能读到EOF,会认为发生异常,报告一个错误。

因此在使用2.6.17之前版本内核的系统中,我们无法依赖封装epoll的底层连接库来实现对对端关闭连接事件的检测,只能通过上层读取数据进行区分处理。

因此在使用2.6.7版本内核中增加EPOLLRDHUP事件,表示对端断开连接,关于添加这个事件的理由可以参见 http://lkml.org/lkml/2003/7/12/116。


在使用2.6.17之后版本内核的服务器系统中,对端连接断开触发的epoll事件会包含EPOLLIN | EPOLLRDHUP,即0x2001。有了这个事件,对端断开连接的异常就可以在底层进行处理了,不用再移交到上层。


重现这个现象的方法很简单,首先telent到server,然后什么都不做直接退出,查看在不同系统中触发的事件码。


注意,在使用2.6.17之前版本内核的系统中,sys/epoll.h的EPOLL_EVENTS枚举类型中是没有EPOLLRDHUP事件的,所以带EPOLLRDHUP的程序无法编译通过。

1 0
原创粉丝点击