免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5777 | 回复: 2
打印 上一主题 下一主题

[C] epoll中使用EPOLLONESHOT 为何还是会返回多个事件? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-09-10 21:13 |只看该作者 |倒序浏览
个人使用epoll做一个多线程的网络服务,模型简单:

1,获取fd,从fd写入请求,然后在该fd上注册EPOLLIN事件,然后将fd放入epoll(EPOLLIN|EPOLLET|EPOLLONESHOT),等待服务器端返回。
2,服务器端返回EPOLLIN事件之后,在fd上读取请求,处理之后释放所有资源以及该fd。

现在问题是,发现有一定概率在这个fd返回EPOLLIN并且读取成功和释放资源之后,这个fd上又会产生一个EPOLLIN事件(我明明已经使用EPOLL_CTL_DEL在epfd上面删除了这个fd了。。),然后由于资源已经被释放掉饿,我的程序就挂了。。。

哪位大神可以告诉我下为啥会发生这么诡异的事情呢。。。

下面是代码片段:
//multi-thread wait on the sem, since there should be only one thread
//at epoll_wait at the same time(L-F model)
sem_wait(wait_sem);

int nfds = epoll_wait(epoll_fd,evts,max_evt_cnt,wait_time_out);

//leader got the fds to proceed
for(int i =0; i < nfds; ++i){
    io_request* req = (io_request*)evts[i].data.ptr;
    int sockfd = req->fd;
    if(evts[i].events & EPOLLIN){
        ev.data.fd=sockfd;
        if(0!=epoll_ctl(epoll_fd,EPOLL_CTL_DEL,sockfd,&ev)){
            switch(errno){
                case EBADF:
                    //multiple EPOLLIN cause EPOLL_CTL_DEL fail
                    WARNING("delete fd failed for EBADF");
                    break;
                default:
                    WARNING("delete fd failed for %d", errno);
            }
         }
         else{
                //currently walk around by just ignore the error fd
                crt_idx.push_back(i);
         }
    }
}

if(crt_idx.size() != nfds)//just warning when the case happen
    WARNING("crt_idx.size():%u != nfds:%d there has been some error!!", crt_idx.size(), nfds);

//current leader waked up next leader, and become a follower
sem_post(wait_sem);

for(int i = 0; i < crt_idx.size(); ++i)
{
    io_request* req = (io_request*)evts[crt_idx[i]].data.ptr;
    ...do business logic...
    ...release the resources & release the client_fd
}

论坛徽章:
0
2 [报告]
发表于 2012-09-11 16:05 |只看该作者
epoll is perfect, bug is caused by the race condition in my code....

i'll be more carefull next time...

so just ignore the thread plz...

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
3 [报告]
发表于 2012-09-12 16:02 |只看该作者
本帖最后由 yulihua49 于 2012-09-12 16:13 编辑
levelset 发表于 2012-09-10 21:13
个人使用epoll做一个多线程的网络服务,模型简单:

1,获取fd,从fd写入请求,然后在该fd上注册EPOLLIN事 ...

似乎EPOLLONESHOT是配合EPOLLLT使用的,
我是这样的,不使用EPOLL_CTL_DEL,用完直接EPOLL_CTL_MOD.
当ET模式,你还没来得及DEL,它又触发了。
ET太快,你不好把握。

一个数据包可能产生N个事件,你要保证这N个事件要能够一致的处理。

一般的触发一次,线程收一些数据,如果没收完,挂起这个连接等待下一次事件。
不要删除这个fd。

下一个事件可能这个线程还没干完就发生了,这是需要采用线程锁来保证处理次序。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP