简体   繁体   English

从其他线程调用FD_SET,选择仍然阻塞

[英]Calling FD_SET from other thread, select still blocking

i came across this problem when writing my first async server with single select call: 我用单一选择调用编写第一个异步服务器时遇到了这个问题:

if( (retv = select((hsock<highestsocket?highestsocket:hsock)+1, &rFdx, &wFdx, &eFdx, 0) ) > 0)
{
   printf("select() ended...\n");
    if(FD_ISSET(hsock, &rFdx))
    {
      // .... handle new connection
    }

    for(unsigned int i=0; i < ClientList.size(); i++)
    {
      ServerClient* client = ClientList[i];

      if(FD_ISSET(client->socket, &rFdx))
      {
        // handle client read
      }
      if(FD_ISSET(client->socket, &wFdx))
      {
           // handle client write
      }    

    }
}

I expect to select to stop waiting and then handle client write when calling FD_SET from other thread. 我希望选择停止等待,然后在从其他线程调用FD_SET时处理客户端写入。

If i call FD_SET on client socket from same thread, everything works as expected. 如果我从同一个线程调用客户端套接字上的FD_SET,一切都按预期工作。 However calling it from other thread does nothing, select keeps waiting until any data is received from client. 但是,从其他线程调用它什么也不做,select会一直等待,直到从客户端收到任何数据。

Of course you can't modify data in one thread and expect that modification to be visible in other threads without the proper synchronization. 当然,您无法在一个线程中修改数据,并且期望在没有正确同步的情况下在其他线程中看到该修改。 It's likely that select reads the fd_set immediately when it's called and then never looks at it again; select可能会在调用时立即读取fd_set ,然后再也不会再查看它了。 but regardless, there's no way of obtaining the necessary synchronization if select has already been called. 但无论如何,如果已经调用了select ,则无法获得必要的同步。 You really need to rethink your design. 你真的需要重新考虑你的设计。 One solution would be the "self-pipe" trick: having a pipe open that select is always looking for input on, and having your other threads send a message over the pipe to cancel any pending select and get the select thread to rescan the table of file descriptors it should be looking at (with the proper synchronization!) and update its own fd_set s. 一个解决方案是“自管”技巧:打开一个管道, select总是在寻找输入,并让你的其他线程通过管道发送消息以取消任何挂起的select并获得select线程重新扫描表应该查看文件描述符(使用正确的同步!)并更新自己的fd_set

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM