2011-04-01 45 views
2

大部分时间这段代码工作得很好。但是有时当可执行文件运行一段时间后,select()会立即超时,然后进入一个奇怪的状态,它会一直被调用,立即超时。然后它必须从外面被杀死。select()在运行很长时间后立即超时(C++)

我的猜测是,标准输入更改加班的方式是错误的 - 这是选择阻止的方式。

环顾StackOverflow,大多数人的select()问题似乎都可以通过确保每次使用宏重置(FD_ZERO & FD_SET)并使用正确的初始参数进行选择来解决。我不认为这是这里的问题。

int   rc  = 0; 
fd_set   fdset; 
struct timeval timeout; 

// -- clear out the response -- // 
readValue = ""; 

// -- set the timeout -- // 
timeout.tv_sec = passedInTimeout; // 5 seconds 
timeout.tv_usec = 0; 

// -- indicate which file descriptors to select from -- // 
FD_ZERO(&fdset); 
FD_SET(passedInFileDescriptor, &fdset); //passedInFileDescriptor = 0 

// -- perform the selection operation, with timeout -- // 
rc = select(1, &fdset, NULL, NULL, &timeout); 


if (rc == -1) // -- select failed -- // 
{ 
    result = TR_ERROR; 
} 
else if (rc == 0) // -- select timed out -- // 
{ 
    result = TR_TIMEDOUT; 
} 
else 
{ 
    if (FD_ISSET(mFileDescriptor, &fdset)) 
    { 
     if(rc = readData(readValue) <= 0) 
     { 
      result = TR_ERROR; 
     } 
    } else { 
     result = TR_SUCCESS; 
    } 
} 
+1

你可以在'rc == 0'情况下添加一些调试代码吗?记录'passedInFileDescriptor'的值,'timeout'和'FD_ISSET(mFileDescriptor,&fdset)'中的字段;如果这个总结的代码是正确的,那么可怕的事情正在发生,并且您可能需要更多的数据来试图将其锁定。 – sarnold 2011-04-01 19:47:47

+0

调用ioctl()和tcsetattr()更改文件描述符的内容。打开文件的公共文件描述符可以在父级和子级之间共享,并且子级可能会更改描述符,然后传播给父级。这假定你不是自己做ioctl()或类似的调用。我正在考虑文件的非阻塞行为。 – 2011-04-01 19:48:50

+0

文件描述符是否已关闭或到达eof? – 2011-04-01 21:27:01

回答

1

当心的“选择”一些implementaions严格执行规范: “NFDs的是在任何三套,外加1编号最高的文件描述符”。 所以,你最好用“passedInFileDescriptor + 1”作为第一个参数来改变“1”。打电话时)

再见

+0

谢谢!我修改了它。行为没有改变,但我很高兴能更正确。 – ag6 2011-04-01 21:44:21

+0

嗨! “mFileDescriptor”总是等于“passedInFileDescriptor”吗?如果不是这样,可能会发生奇怪的事情。例如:如果“mFileDescriptor”错误并且“FD_ISSET”成功并且“readData()> 0”会发生什么? “结果”在你的代码中是未定义的,所以......嗯......好吧,我的只是一个提示。再见! – 2011-04-02 09:17:31

1

在一些操作系统中,timeout被修改; 我不知道这是否可以解决你的问题,但至少你的代码变得更...呃... ...“传统” select来反映不睡觉的时间量。在你的例子中,它看起来并不像你正在重复使用timeout,但确保你在每次调用select之前确实将它重新初始化为5秒。

1

我有同样的问题,它在Windows上工作正常,但不是在Linux上,我有MAXFD设置为最后一个套接字+ 1。它长期运行后定期发生。我选择接受连接,然后第一个电话选择定期超时。

0

看看这段代码:

if (FD_ISSET(mFileDescriptor, &fdset)) 
{ 
    if(rc = readData(readValue) <= 0) 
    { 
     result = TR_ERROR; 
    } 
} else { 
    result = TR_SUCCESS; 
} 

有两件事情在这里烦我:

  1. 如果你的FD中没有任何数据(比如说,一个错误发生), FD_ISSET ()将返回false并且您的函数返回 TR_SUCCESS!?
  2. you FD_SET(passedInFileDescriptor, &fdset),但请检查另一个 值:FD_ISSET(mFileDescriptor, &fdset)。如果mFileDescriptor!= passedInFileDescriptor在某些时候,你会落入我的第一个 假设。

应该这样看:

if (FD_ISSET(passedInFileDescriptor, &fdset)) 
{ 
    if(rc = readData(readValue) <= 0) 
    { 
     result = TR_ERROR; 
    } 
    else 
    { 
     result = TR_SUCCESS; 
    } 
} 
else 
{ 
    result = TR_ERROR; 
} 

没有?

(编辑:也this answer也指出你使用的select()一个坏的问题high_fd值)

另一个编辑:好吧,看起来像人再也没有回来......令人沮丧。

相关问题