2011-11-21 58 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庫代碼以返回描述符,或者甚至可以自動將其刪除。