Menu

epoll 监听不到close事件

reg2011
2012-06-03
2014-02-27
  • reg2011

    reg2011 - 2012-06-03

    epoll  监听不到close事件,不知为何,谢谢!

     
  • chenbin0522

    chenbin0522 - 2012-06-05

    我也发现了,如果客户端不掉用UDT::close(fhandle) 那么服务器端可以读到错误。如果客户端调用UDT::close(fhandle)就收不到,比较奇怪。我是客户端和服务器端在一台电脑上,不知到有没有关系。

     
  • Yunhong Gu

    Yunhong Gu - 2012-06-05

    是个bug,正在修改,估计一两天之内会把新的代码放到cvs上去。

     
  • Yunhong Gu

    Yunhong Gu - 2012-06-06

    已经更新了CVS。谢谢。

     
  • yavey

    yavey - 2013-01-29

    请问这个更新是版本5?

     
  • bluex

    bluex - 2014-02-25

    确实有这个BUG。。。在底层检测到broken的socket时,然后调用close候会添加一个ERROR事件,但是并没添加成功,代码如下:
    void CUDT::close()

    .............
    s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_ERR, true);
    .............

    但是跟踪代码发现update_events(m_SocketID, m_sPollID, UDT_EPOLL_ERR, true)会调用:
    update_epoll_sets(uid, p->second.m_sUDTSocksEx, p->second.m_sUDTExcepts, enable);
    进而调用
    void update_epoll_sets(const UDTSOCKET& uid, const set<UDTSOCKET>& watch, set<UDTSOCKET>& result, bool enable)
    {
    if (enable && (watch.find(uid) != watch.end()))
    {
    result.insert(uid);
    }
    else if (!enable)
    {
    result.erase(uid);
    }
    }

    此时的set<UDTSOCKET>& watch即为p->second.m_sUDTExcepts,但是p->second.m_sUDTExcepts为empty(),
    所以事件添加不成功,导致上层不能接受到事件。
    为什么m_sUDTExcepts为空,查看代码就能发现跟epoll之前调用的add_usock有关,当我们需要关注ERROR时,并没有往这里面添加socket描述符:
    int CEPoll::add_usock(const int eid, const UDTSOCKET& u, const int* events)
    {
    CGuard pg(m_EPollLock);

    map<int, CEPollDesc="">::iterator p = m_mPolls.find(eid);
    if (p == m_mPolls.end())
    throw CUDTException(5, 13);

    if (!events || (events & UDT_EPOLL_IN))
    p->second.m_sUDTSocksIn.insert(u);
    if (!events || (
    events & UDT_EPOLL_OUT))
    p->second.m_sUDTSocksOut.insert(u);

    return 0;
    }

    查看函数int CEPoll::wait(const int eid, set<UDTSOCKET> readfds, set<UDTSOCKET> writefds, int64_t msTimeOut, set<SYSSOCKET> lrfds, set<SYSSOCKET> lwfds)可以发现:即使有一个error事件触发,在事件收集的时候也是合并为EPOLL_IN事件来处理的。

      // Sockets with exceptions are returned to both read and write sets.
      if ((NULL != readfds) && (!p->second.m_sUDTReads.empty() || !p->second.m_sUDTExcepts.empty()))
      {
         *readfds = p->second.m_sUDTReads;
         for (set<UDTSOCKET>::const_iterator i = p->second.m_sUDTExcepts.begin(); i != p->second.m_sUDTExcepts.end(); ++ i)
            readfds->insert(*i);
         total += p->second.m_sUDTReads.size() + p->second.m_sUDTExcepts.size();
      }
    

    所以可以这样修改:
    1)在close函数里面修改 s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_ERR, true);
    为 s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_IN, true);
    这样就能导致上层收到一个读事件。
    2)然后上层调用recv或者recvmsg,此时因为socket已经在udt层面不存在了,会引发一个异常,这时候要在异常里面做处理
    就是剔除跟这个socket有关的事件,职位为false,否则会导致这个事件一直存在,不停的循环告诉上层有读的事件发生。
    所以需要修改recv和recvmsg函数的异常处理分支
    int CUDT::recv(UDTSOCKET u, char buf, int len, int)
    {
    try
    {
    CUDT
    udt = s_UDTUnited.lookup(u);
    return udt->recv(buf, len);
    }
    catch (CUDTException e)
    {
    s_UDTUnited.m_EPoll.remove_events(u); //////////因为bug新增行remove_events在源代码里面是没有的。
    s_UDTUnited.setError(new CUDTException(e));
    return ERROR;
    }
    catch (...)
    {
    s_UDTUnited.setError(new CUDTException(-1, 0, 0));
    return ERROR;
    }
    }
    recvmsg函数的修改同上。。。。。。
    新增函数:
    void CEPoll::remove_events(const UDTSOCKET& uid)
    {
    CGuard pg(m_EPollLock);

    map<int, CEPollDesc>::iterator p;
    for (p = m_mPolls.begin(); p != m_mPolls.end(); ++p)
    { 
        p->second.m_sUDTReads.erase(uid);
        p->second.m_sUDTWrites.erase(uid);
        p->second.m_sUDTExcepts.erase(uid);
    }
    

    }

     
  • bluex

    bluex - 2014-02-26

    我用的是utd的最新版本udt4.11,udt5好像还没出来。。。

     
    • wang hui

      wang hui - 2014-02-26
      <HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=gb2312"> </HEAD>

      <BODY>

      我最喜欢淘东西了,最近运气好,前几天看到这个活动,拍了两双,没想到发过来去专柜检验确实是正品~赚了~还有情侣款!http://dfhtdh.gxsl.net


      This is an automatic reply, confirming that your e-mail was received.Thank you



      邮箱使用小提示


      想让对方更及时看到你的邮件,可以试试发到"对方手机号@163.com"。



      无需事先开通,还有短信提醒。了解网易手机邮箱详情


      </body>
      </html>

       
      • wang hui

        wang hui - 2014-02-26
        <HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=gb2312"> </HEAD>

        <BODY>

        我最喜欢淘东西了,最近运气好,前几天看到这个活动,拍了两双,没想到发过来去专柜检验确实是正品~赚了~还有情侣款!http://dfhtdh.gxsl.net


        This is an automatic reply, confirming that your e-mail was received.Thank you



        邮箱使用小提示


        想让对方更及时看到你的邮件,可以试试发到"对方手机号@163.com"。



        无需事先开通,还有短信提醒。了解网易手机邮箱详情


        </body>
        </html>

         
        • wang hui

          wang hui - 2014-02-26
          <HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=gb2312"> </HEAD>

          <BODY>

          我最喜欢淘东西了,最近运气好,前几天看到这个活动,拍了两双,没想到发过来去专柜检验确实是正品~赚了~还有情侣款!http://dfhtdh.gxsl.net


          This is an automatic reply, confirming that your e-mail was received.Thank you



          邮箱使用小提示


          想让对方更及时看到你的邮件,可以试试发到"对方手机号@163.com"。



          无需事先开通,还有短信提醒。了解网易手机邮箱详情


          </body>
          </html>

           
  • bluex

    bluex - 2014-02-27

    上次回复修改这个bug并不完善,还有自动检测的地方,并没有关闭事件通知到上层,接着上面的帖子,还要修稿到文件为api.cpp,在函数
    void CUDTUnited::checkBrokenSockets()里面加上事件通知
    //EPOLL SIGNAL
    m_EPoll.update_events(i->first, i->second->m_pUDT->m_sPollID, UDT_EPOLL_IN, true);

     
    • wang hui

      wang hui - 2014-02-27
      <HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=gb2312"> </HEAD>

      <BODY>

      我最喜欢淘东西了,最近运气好,前几天看到这个活动,拍了两双,没想到发过来去专柜检验确实是正品~赚了~还有情侣款!http://dfhtdh.gxsl.net


      This is an automatic reply, confirming that your e-mail was received.Thank you



      邮箱使用小提示


      想让对方更及时看到你的邮件,可以试试发到"对方手机号@163.com"。



      无需事先开通,还有短信提醒。了解网易手机邮箱详情


      </body>
      </html>

       
      • wang hui

        wang hui - 2014-02-27
        <HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=gb2312"> </HEAD>

        <BODY>

        我最喜欢淘东西了,最近运气好,前几天看到这个活动,拍了两双,没想到发过来去专柜检验确实是正品~赚了~还有情侣款!http://dfhtdh.gxsl.net


        This is an automatic reply, confirming that your e-mail was received.Thank you



        邮箱使用小提示


        想让对方更及时看到你的邮件,可以试试发到"对方手机号@163.com"。



        无需事先开通,还有短信提醒。了解网易手机邮箱详情


        </body>
        </html>

         
        • wang hui

          wang hui - 2014-02-27
          <HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=gb2312"> </HEAD>

          <BODY>

          我最喜欢淘东西了,最近运气好,前几天看到这个活动,拍了两双,没想到发过来去专柜检验确实是正品~赚了~还有情侣款!http://dfhtdh.gxsl.net


          This is an automatic reply, confirming that your e-mail was received.Thank you



          邮箱使用小提示


          想让对方更及时看到你的邮件,可以试试发到"对方手机号@163.com"。



          无需事先开通,还有短信提醒。了解网易手机邮箱详情


          </body>
          </html>

           

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.