2011-11-21 62 views
4

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

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

一旦描述符加入到pollset,这些然后由OS /内核处理,我看不出有任何检索他们能够迭代的方式。将这些维护在我自己的列表中可能会进一步导致其他问题,因为在套接字关闭时,我需要以某种方式清理它们,这会自动发生在内核中的pollset中。

有什么建议吗?

回答

2

这听起来很可怕,但是当它发生时它是一个紧急情况。所以,我建议通过工作pollset中的所有描述符,并试图对描述符执行操作,如果描述符是假的,将触发该错误。例如,您可以创建一个新的临时pollset,并尝试使用非阻塞式零超时轮询操作,并查看是否可以获取该错误。

如果你有不止,比方说,在你pollset十几描述,你可能会考虑一个二进制搜索,而不是一在一次一个方法。您可以将一半描述符放入临时pollset中,然后执行操作。如果失败了,你知道你在你尝试的集合中有一个伪造的描述符;分成两部分再试一次;如果没有失败,则可以假定伪造描述符位于另一个集合中,并且可以验证另一半是否失败或假定它会将余数分成两部分,然后重试。继续下去,直到你隔离了一个失败的描述符。显然,如果你有几个虚假描述符而不是一个,你可能需要重复这个过程几次。

随着一个描述符孤立的,你可以决定你需要做些什么和怎么样。如果/当问题再次出现时,您可以重复隔离过程。显然,除非您首先发现问题,否则您不会尝试这种方式。但是当事情出错时,你需要将问题孤立起来,而这会(应该)实现这一点。

+0

问题是,一旦这些描述符加入到pollset,这些然后由OS /内核处理,我看不出有任何检索他们能够迭代的方式。 – b0ti

+0

你确定吗?我没有详细看过,但是你应该能够找出哪些描述符在轮询集合中,不过如果只是这样,你可以在轮询集合关闭后从轮询集合中删除描述符。如果最糟糕的是最坏的情况,那么您必须在给定的轮询集中保留独立的描述符记录,以便您可以执行此操作。 –

+0

查看轮询集的APR文档,您显然希望知道哪些描述符在给定的轮询集中。您可以将描述符添加到轮询集,或从轮询集中移除(已知)描述符。不清楚是否有方法遍历轮询集中的描述符。 –

0

原来,我是做了close()方法在其上正在另一个线程,并根据选择的pollset()实现轮询不喜欢这个套接字描述符。 另一方面,当选择检测到无效的套接字时,可以修改apr库代码以返回描述符,或者甚至可以自动将其删除。