我有一个服务器应用程序,它使用异步I/O处理网络客户机。接受客户机连接,然后将其添加到一个描述符集,该描述符集可以使用poll/epoll/select/etc进行监视。我正在使用apr_poll set_poll()apache apr library调用来检查可以读取或写入的描述符。根据平台的不同,它在内部使用epoll/poll/select/etc。
问题是,不知何故,一个套接字描述符损坏,apr_pollset_poll返回errno 10038,这是wsaenotsock:试图对非套接字的内容执行操作。不幸的是,这导致我的应用程序完全停止工作,而不是仅仅能够踢出特定的客户端连接。
如果我可以忽略或从描述符集中删除这个套接字,那么它可以继续工作并正确地读/写其他套接字。我知道我应该找出导致套接字损坏的根本原因,但我需要一个故障保护解决方案。
一旦将描述符添加到pollset中,这些描述符就由os/内核处理,我看不到检索它们的方法,无法进行迭代。在我自己的列表中维护它们可能会进一步产生其他问题,因为在socket关闭时,我需要以某种方式清理它们,这对于内核内pollset是自动发生的。
有什么建议吗?
最佳答案
听起来很可怕,但一旦发生就成了紧急情况。因此,我建议检查工作pollset中的所有描述符,并尝试对该描述符执行一个操作,如果该描述符是假的,则会触发该错误。例如,您可以创建一个新的临时轮询集,然后尝试非阻塞的零超时轮询操作,并查看是否可以获取错误。
如果你的pollset中有超过12个描述符,你可以考虑使用二进制搜索,而不是一次一个的方法。您可以将一半描述符放入临时pollset中,然后执行该操作。如果它失败了,你知道你尝试过的集合中有一个假的描述符;分成两个,然后再试一次;如果它没有失败,你可以假设这个假的描述符在另一个集合中,你可以验证另一半失败了,或者假设它会失败,然后把剩下的一分为二,再试一次。继续,直到隔离出一个失败的描述符。显然,如果您有几个伪描述符,而不是只有一个,那么您可能需要重复该过程几次。
在隔离一个描述符的情况下,您可以决定需要对它做什么以及如何做。如果/当问题再次出现时,您可以重复隔离过程。显然,除非你一开始就发现了问题,否则你不会尝试这个。但当事情出错时,你需要把问题隔离开来,这会(应该)实现这个目标。