免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: converse
打印 上一主题 下一主题

郁闷的select出错:Bad file descriptor [复制链接]

论坛徽章:
0
11 [报告]
发表于 2007-06-15 10:13 |只看该作者
你同时监视几个fd?

应该成fd_set中取出来看。

原帖由 converse 于 2007-6-15 10:08 发表


在select出错之后用了fstat查询fd,也是没有报错,fstat返回0.

论坛徽章:
0
12 [报告]
发表于 2007-06-15 10:23 |只看该作者
原帖由 思一克 于 2007-6-15 10:13 发表
你同时监视几个fd?

应该成fd_set中取出来看。



不好意思,我刚刚没有出错是因为没有传入stat参数给fstat,原来认为如果不关心这个值可以不用传,现在把这个参数传进去就报错了,同select一样是:bad file descriptor,是第一个接收过来的fd,但是我的程序中在处理这个fd发送的请求之前并没有关闭这个fd的操作啊.

修改过的Poll函数如下:


  1. int CMsgServer::Poll()
  2. {
  3.     int nFdNum, nEvent, nFd, nRet;

  4.     // 将server listen fd加入fdset中
  5.     FD_SET(m_nListenFd, &m_ReadSet);
  6.     //FD_SET(m_nListenFd, &m_ExpSet);

  7.     LogMsg("nListenFd = %d", m_nListenFd);

  8.     struct stat tStat;
  9.     for(int i = 0; i < m_nMaxCon; ++i)
  10.     {
  11.         nFd = m_szConnections[i].nFd;
  12.         if (-1 != nFd && FD_ISSET(nFd, &m_ReadSet))
  13.         {
  14.             printf("%d in readset\n", nFd);
  15.             if (-1 == fstat(nFd, &tStat))
  16.             {
  17.                 printf("fstat %d error:%s", nFd, strerror(errno));
  18.             }
  19.             else
  20.             {
  21.                 if (!S_ISSOCK(tStat.st_mode))
  22.                 {
  23.                     printf("fd %d isnot socket", nFd);
  24.                 }
  25.             }
  26.         }
  27.     }
  28.     if (-1 == fstat(m_nListenFd, &tStat))
  29.     {
  30.         printf("fstat %d error:%s", m_nListenFd, strerror(errno));
  31.     }       
  32.     if (!S_ISSOCK(tStat.st_mode))
  33.     {
  34.         printf("listen fd %d isnot socket", m_nListenFd);
  35.     }
  36.                                
  37.     // 轮询fd集合
  38.     while (true)
  39.     {
  40.         //if (0 > (nFdNum = select(m_nMaxFd + 1, &m_ReadSet, NULL, NULL, NULL)))
  41.                 LogMsg("maxfd = %d, nListenFd = %d", m_nMaxFd, m_nListenFd);
  42.                 printf("maxfd = %d, nListenFd = %d\n", m_nMaxFd, m_nListenFd);       

  43.         if (0 > (nFdNum = select(m_nMaxFd + 1, &m_ReadSet, NULL, &m_ExpSet, NULL)))
  44.         {
  45.             if (EINTR == errno)
  46.             {
  47.                 continue;
  48.             }
  49.             else
  50.             {
  51.                 LogMsg("[%s] [%s] [%d]: select failed: %s, nListenFd = %d, nMaxFd = %d"
  52.                         , __FILE__, __FUNCTION__, __LINE__
  53.                         , strerror(errno)
  54.                         , m_nListenFd
  55.                         , m_nMaxFd);
  56.                                
  57.                 return -1;
  58.             }
  59.         }
  60.         else
  61.         {
  62.             return 0;
  63.         }
  64.     }
  65. }
复制代码

论坛徽章:
0
13 [报告]
发表于 2007-06-15 10:54 |只看该作者
就是某个fd在给fd_set前已经被关闭了

论坛徽章:
0
14 [报告]
发表于 2007-06-15 11:02 |只看该作者
原帖由 思一克 于 2007-6-15 10:54 发表
就是某个fd在给fd_set前已经被关闭了


这就是最邪门的地方,accept之后我马上用fstat查看了状态是正确的fd,但是下一个server主循环开始的时候fstat就不对了,而我在每个调用关闭fd的地方都打了log,没有看到调用这些语句.

如果是我的测试客户端程序写的有问题也不应该,因为我换了别的方式是可以收到数据的.

论坛徽章:
0
15 [报告]
发表于 2007-06-15 11:05 |只看该作者
是thread程序?

论坛徽章:
0
16 [报告]
发表于 2007-06-15 11:06 |只看该作者

回复 15楼 思一克 的帖子

目前还是单进程的,测试完毕之后改成多进程的.

论坛徽章:
0
17 [报告]
发表于 2007-06-15 11:15 |只看该作者
把log下来的信息给大家参考一下吧

论坛徽章:
0
18 [报告]
发表于 2007-06-15 15:46 |只看该作者
我终于明白问题出在哪里了,

我对struct onnection的定义如下:

  1. typedef struct Connection
  2. {
  3.     int                 nFd;        // 连接套接字
  4.     time_t              nStartTime; // 接收连接的时间

  5.     Connection_State    nState;    // 连接状态
  6.     bool                bReadable;  //
  7.     bool                bWriteable; //
  8.     string              strReq;     // 请求字符串
  9.     string              strRet;     // 回复字符串

  10.     Connection()
  11.         : nFd(-1)
  12.         , nState(CON_STATE_CLOSE)         
  13.         , nStartTime(0)                                             
  14.         , bReadable(false)                                                                     
  15.         , bWriteable(false)                                                                     
  16.     {
  17.     }

  18.     ~Connection()
  19.     {
  20.         if (-1 != nFd)
  21.         {
  22.             close(nFd);
  23.             nFd = -1;
  24.         }
  25.         nState = CON_STATE_CLOSE;
  26.     }
  27. }Connection;
复制代码


而在Accept函数的处理中,有几段代码:


  1.        Connection tCon;
  2.         tCon.nFd = nFd;
  3.         tCon.nStartTime = time(NULL);            

  4.         m_listCon.push_back(tCon);
复制代码


我的本意是把连接上的fd存放进入这个list中,但是tCon是局部对象,出了这个函数调用自己的析构函数,把接收的fd给关闭了.
于是再去select的时候就出错了.

论坛徽章:
0
19 [报告]
发表于 2007-06-15 15:52 |只看该作者
哈。

C++,和多thread都是棘手BUG的发源地。

你没有主动让它做的事情,他会在背后(偷偷地)给你做了。




原帖由 converse 于 2007-6-15 15:46 发表
我终于明白问题出在哪里了,

我对struct onnection的定义如下:
[code]
typedef struct Connection
{
    int                 nFd;        // 连接套接字
    time_t              nStartTime; // 接收连 ...

论坛徽章:
0
20 [报告]
发表于 2007-06-15 15:53 |只看该作者
估计是 select 出来事件后 在循环体内对句柄列表进行了 修改。
是逻辑问题
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP