4

我有一个服务器应用程序,它使用异步 i/o 处理网络客户端。客户端连接被接受,然后添加到描述符集中,可以使用 poll/epoll/select/etc 进行监视。我正在使用 apr_pollset_poll() apache APR 库调用来检查可以读取或写入的描述符。这取决于平台在内部使用 epoll/poll/select/etc。

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

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

有什么建议么?

4

2 回答 2

2

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

如果您的投票集中有多个描述符,例如,您可能会考虑使用二进制搜索而不是一次一个的方法。您可以将一半的描述符放入临时轮询集中,然后执行操作。如果它失败了,你就知道你尝试的集合中有一个虚假的描述符;一分为二再试一次;如果它没有失败,您可以假定虚假描述符在另一组中,并且您可以验证另一半失败或假设它将失败并将其余部分分成两部分并重试。继续进行,直到您隔离了一个失败的描述符。显然,如果您有多个虚假描述符而不仅仅是一个,您可能需要重复该过程几次。

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

于 2011-11-21T15:52:45.290 回答
0

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

于 2011-11-23T22:20:59.427 回答