C 如何检测无效的fd/句柄

C 如何检测无效的fd/句柄,c,network-programming,apr,C,Network Programming,Apr,我有一个服务器应用程序,它通过异步I/o处理网络客户端。接受客户端连接,然后将其添加到一个描述符集,该描述符集可以通过poll/epoll/select/etc进行监视。我正在使用apr\u pollset\u poll()apache apr库调用来检查可以读取或写入的描述符。这在内部根据平台使用epoll/poll/select/etc 问题是其中一个套接字描述符不知何故损坏,apr_pollset_poll返回errno 10038,即WSAENOTSOCK:尝试对非套接字的对象执行操作。

我有一个服务器应用程序,它通过异步I/o处理网络客户端。接受客户端连接,然后将其添加到一个描述符集,该描述符集可以通过poll/epoll/select/etc进行监视。我正在使用apr\u pollset\u poll()apache apr库调用来检查可以读取或写入的描述符。这在内部根据平台使用epoll/poll/select/etc

问题是其中一个套接字描述符不知何故损坏,apr_pollset_poll返回errno 10038,即WSAENOTSOCK:尝试对非套接字的对象执行操作。不幸的是,这导致我的应用程序完全停止工作,而不是仅仅能够启动特定的客户端连接。 如果我可以忽略或从描述符集中删除这个套接字,那么它可以继续工作并正确地读/写其他套接字。我知道我应该找到导致套接字损坏的根本原因,但我需要一个故障保护解决方案

一旦描述符被添加到pollset中,它们就会由OS/内核处理,我看不出有任何方法可以检索它们来进行迭代。在我自己的列表中维护它们可能会进一步产生其他问题,因为在套接字关闭时,我需要以某种方式清理它们,这对于内核内轮询集是自动发生的


有什么建议吗?

听起来很可怕,但发生这种情况时是紧急情况。因此,我建议检查工作轮询集中的所有描述符,并尝试在该描述符上执行一个操作,如果该描述符是假的,则会触发该错误。例如,您可以创建一个新的临时轮询集,然后尝试非阻塞零超时轮询操作,看看是否可以得到错误

如果你在PultSeT中有十几个描述符,你可以考虑二进制搜索而不是一次一次的方法。您可以将一半描述符放入临时轮询集中,然后执行该操作。如果失败了,你知道在你尝试的集合中有一个伪造的描述符;一分为二,再试一次;如果它没有失败,您可以假设伪描述符在另一个集合中,您可以验证另一半是否失败,或者假设它会失败,并将剩余的部分一分为二,然后重试。继续进行,直到您隔离出一个失败的描述符。显然,如果你有几个伪造的描述符而不是一个,你可能需要重复这个过程几次


隔离一个描述符后,您可以决定需要对它做什么以及如何做。如果问题再次出现,您可以重复隔离过程。显然,除非您首先发现问题,否则您不会尝试此方法。但是当出现问题时,您需要隔离问题,这将(应该)实现这一点。

结果是,我在另一个线程中轮询的套接字描述符上执行close(),基于select()的pollset实现不喜欢这样。
另一方面,当select检测到无效套接字时,可以修改apr库代码以返回描述符,甚至可以自动将其删除。

问题是,一旦描述符添加到pollset中,这些都是由OS/内核处理的,我看不到任何方法可以检索它们来进行迭代。你确定吗?我还没有详细研究过,但是您应该能够找到轮询集中的描述符,如果您能够在轮询集关闭后从轮询集中删除描述符的话。如果出现最坏的情况,您必须在给定的轮询集中保留描述符的独立记录,以便执行此操作。查看轮询集的APR文档,您显然需要知道给定轮询集中有哪些描述符。您可以向轮询集中添加描述符,也可以从轮询集中删除(已知)描述符。不清楚是否有方法在轮询集中迭代描述符。是的,可以添加和删除描述符,但为此,您需要有描述符。不幸的是,对于select()和epoll()实现,描述符列表分别保存在私有数组和内核中。