Linux 半开套接字上的select()在关闭()时不返回?

Linux 半开套接字上的select()在关闭()时不返回?,linux,sockets,select,Linux,Sockets,Select,我正在阻塞套接字上执行select(),没有超时select(sock+1,&rfd,NULL,NULL,NULL) 这发生在目标是分派传入数据的线程中。另一个监视线程正在管理与对等方的保持活动状态,当它检测到死连接时,它将关闭套接字 在这种情况下,我希望select()返回-1。它在Windows上这样做,但在Linux上永远不会这样做,因此当对等线程不正常地消失时,调度线程将永远被锁定。为了完整性,还有待传输的数据,我尝试使用SO_LINGER,但这并没有改变任何事情 这个问题可以通过在se

我正在阻塞套接字上执行
select()
,没有超时
select(sock+1,&rfd,NULL,NULL,NULL)

这发生在目标是分派传入数据的线程中。另一个监视线程正在管理与对等方的保持活动状态,当它检测到死连接时,它将关闭套接字

在这种情况下,我希望
select()
返回
-1
。它在Windows上这样做,但在Linux上永远不会这样做,因此当对等线程不正常地消失时,调度线程将永远被锁定。为了完整性,还有待传输的数据,我尝试使用
SO_LINGER
,但这并没有改变任何事情

这个问题可以通过在
select()
中设置一个超时来解决,在关闭和超时之后,
select()
最终会以
-1
退出,但我想,阅读文档时,没有超时的
select()
在关闭时仍然会退出,即使对等方没有响应


我是误用了
select()
还是有更好的方法来处理半开插槽?

是的,您误用了
select
人工选择
说明:

如果select()监视的文件描述符在另一个线程中被关闭,则结果是未指定的。在某些UNIX系统上,select()取消阻止并返回,并指示文件描述符已准备就绪(后续I/O操作可能会失败并出错,除非在select()返回和执行I/O操作之间再次打开文件描述符)。在Linux(和其他一些系统)上,关闭另一个线程中的文件描述符对select()没有影响。总之,在此场景中依赖于特定行为的任何应用程序都必须被视为有缺陷

所以您不能关闭来自其他线程的连接。不幸的是,
poll
也有同样的问题


编辑

有几种可能的解决方案,我没有关于您的应用程序的足够信息。可考虑以下变更:

  • 如果您在linux上,请使用
    epoll
    而不是
    select
    ,如果您在其他操作系统上,请使用其他现代轮询机制<代码>选择是一个非常古老的功能,它是在没有认真考虑线程的情况下及时设计的
  • 在选择线程和保持活动线程之间建立通信通道。当keep-alive线程检测到一个死的对等线程时,不要关闭套接字本身,而是指示select线程这样做。通常,它可以通过本地套接字完成。本地套接字被添加到select描述符集,当keep-alive线程向其写入内容时,select线程将被唤醒并可以执行操作
谢谢!像往常一样,我应该有更好的RTFM。。。话虽如此,您如何在没有超时的情况下使用select()并处理对等方变暗时发生的问题?我的应用程序必须在Windows、OSX和Linux上运行,因此epoll无法工作(当然,我可以#ifdef各种选项),但添加一个本地套接字并在其上选择将起作用。谢谢