[英]close on socket not releasing file descriptor
在對我編寫的某些服務器代碼進行壓力測試時,我注意到即使我在描述符句柄上調用close()(並驗證錯誤的結果),也沒有釋放描述符,最終導致accept()返回錯誤“打開文件太多”。
現在我明白這是因為ulimit,我不明白為什么如果我在每個同步接受/讀/發送周期后調用close(),我會遇到它?
我通過運行帶有lsof的監視來驗證描述符實際上是在那里:
ctsvr 9733 mike 1017u sock 0,7 0t0 3323579 can't identify protocol ctsvr 9733 mike 1018u sock 0,7 0t0 3323581 can't identify protocol ...
當然,大約有1000個左右。 此外,使用netstat檢查我可以看到沒有掛起的TCP狀態(沒有WAIT或STOPPED或任何東西)。
如果我只是從客戶端執行單個connect / send / recv,我會注意到套接字確實保留在lsof中; 所以這甚至不是負載問題。
服務器在Ubuntu Linux 64位計算機上運行。
有什么想法嗎?
因此,使用strace(感謝Gearoid),我不知道我是如何生活的,我注意到我實際上是在關閉描述符。
然而。 為了后代,我露出了愚蠢的錯誤:
Socket::Socket() : impl(new Impl) {
impl->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
....
}
Socket::ptr_t Socket::accept() {
auto r = ::accept(impl->fd, NULL, NULL);
...
ptr_t s(new Socket);
s->impl->fd = r;
return s;
}
正如您所看到的,我的構造函數立即分配了一個套接字,然后我用accept返回的描述符替換了描述符 - 創建了一個泄漏。 我已經將獨立的Acceptor類中的接受代碼重構為Socket類而不更改它。
使用strace我可以很容易地看到每次運行socket()導致我的燈泡時刻。
謝謝大家的幫助!
你有沒有在close()之后調用perror()? 我認為返回的字符串會給你一些幫助;
您最有可能掛在recv()
或send()
命令上。 考慮使用setsockopt
設置超時。
當套接字在另一端關閉時,我注意到lsof上有類似的輸出,但是我的線程在等待數據的recv()
命令上保持套接字打開。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.