linux下使用setitimer時accept返回Interrupted system call

    Android平臺下程序中的一個線程使用setitimer,而主進程則作爲套接字接收服務器,但是卻經常出現 accept返回Interrupted system call錯誤,

追尋原因及解決方法:

 

 

 

出自unix網絡編程(第三版)第五章 P115頁。

 

我們用術語慢系統調用(slow system call)描述accept函數,該術語也適用於那些可能永遠阻塞的系統調用。永遠阻塞的系統調用有可能永遠無法返回,多數網絡支持函數都屬於這一類。舉例來說,如果沒有客戶連接到服務器上,那麼服務器的accept調用就沒有返回的保證,類似的如果客戶端從未發送過數據,那麼read調用將永不返回。其他慢系統調用的例子是對管道和終端設備的讀和寫。一個值得注意的例外是磁盤IO,它們一般都會返回到調用者(假設沒有災難性的硬件事故)。
  適用於慢系統調用的基本規則是:當阻塞於某個慢系統調用的一個進程捕獲某個信號且相應處理函數返回時,該系統調用可能返回一個EINTR錯誤。所以,我們必須對慢系統調用返回的EINTR有所準備。
  爲了處理被中斷的accept,可以包裝證:

 for (;;) {
    if ((connfd = accept(listenfd, NULL, NULL)) < 0) {
  if (errno == EINTR)
    continue;
  else
    err_sys("accept error");
    }  
        }
  這段代碼所做的事情就是自己重啓被中斷的系統調用。對於accept以及諸如read、write、select和open之類的函數,這是適合的。不過有一個函數我們不能重啓:connect。如果該函數返回EINTR,我們就不能再次調用它,否則將立即返回一個錯誤。當connect被一個捕獲信號中斷而且不自動重啓時,我們必須調用select來等待連接完成。

http://www.cs.moravian.edu/pipermail/cs320/2008-February/000040.html

 

 

 

 

   在本人的程序中,爲了能夠使用一種機制,使accept不會被SIGALRM信號中斷,嘗試了使用pthread_sigmask函數,但pthread_sigmask 總是返回失敗。無奈嘗試了下再起一個線程,一個線程作爲timer,另一個線程進行套接字數據接收處理,主線程通過等待互斥量來進行阻塞(不能使用sleep,Timer和sleep也會存在衝突,timer到時後的SIGALRM信號會導致sleep被喚醒),測試問題沒有出現。。。

 

    多個線程的SIGALRM信號不會影響? 原因沒有想明白,懷疑和Android內核處理有關。

 

 

 

發佈了65 篇原創文章 · 獲贊 39 · 訪問量 42萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章