【網絡編程】——connect函數遇見EINTR的處理


  最近在公司項目中突然報錯如下 “connect: Interrupted system call”, 經過查找代碼發現是在創建 socket 中執行了 connect 函數失敗導致。上網查閱資料發現這是 信號中斷EINTR 與 慢系統調用 的問題。

  慢系統調用:可能永遠阻塞的系統調用

  EINTR說明:如果進程在一個慢系統調用(slow system call)中阻塞時,當捕獲到某個信號且相應信號處理函數返回時,這個系統調用被中斷,調用返回錯誤,設置errno為EINTR(相應的錯誤描述為“Interrupted system call”)。

  在博客 http://blog.csdn.net/benkaoya/article/details/17262053  信號中斷 與 慢系統調用 有詳細介紹。

  那么針對 EINTR 錯誤應該如何處理,或者如何規避這類問題。 建議查看此鏈接 http://www.madore.org/~david/computers/connect-intr.html

  以下給出一些常用的處理方法:

    ◆ 人為重啟被中斷的系統調用

    ◆ 安裝信號時設置 SA_RESTART屬性(該方法對有的系統調用無效)

    ◆  忽略信號(讓系統不產生信號中斷)

人為重啟被中斷的系統調用

  人為當碰到EINTR錯誤的時候,有一些可以重啟的系統調用要進行重啟,而對於有一些系統調用是不能夠重啟的。例如:accept、read、write、select、和open之類的函數來說,是可以進行重啟的。不過對於套接字編程中的connect函數我們是不能重啟的,若connect函數返回一個EINTR錯誤的時候,我們不能再次調用它,否則將立即返回一個錯誤。針對connect不能重啟的處理方法是,必須調用select來等待連接完成。

  對於非 connect 函數可以嘗試使用重新執行系統調用的方法。



  對於 connect 函數出現 EINTR 錯誤的時候,處理過程如下:

 1 int check_conn_is_ok(socket_t sock) {
 2     struct pollfd fd;
 3     int ret = 0;
 4     socklen_t len = 0;
 5 
 6     fd.fd = sock;
 7     fd.events = POLLOUT;
 8 
 9     while ( poll (&fd, 1, -1) == -1 ) {
10         if( errno != EINTR ){
11             perror("poll");
12             return -1;
13         }
14     }
15 
16     len = sizeof(ret);
17     if ( getsockopt (sock, SOL_SOCKET, SO_ERROR,
18                      &ret,
19                      &len) == -1 ) {
20                 perror("getsockopt");
21         return -1;
22     }
23 
24     if(ret != 0) {
25         fprintf (stderr, "socket %d connect failed: %s\n",
26                  sock, strerror (ret));
27         return -1;
28     }
29 
30     return 0;
31 }

  調用時如下:

if(connnect()) {
    if(errno == EINTR) {
        if(check_conn_is_ok() < 0) {
              perror();
              return -1;
        }
        else {
             printf("connect is success!\n");
        }
    }
    else {
         perror("connect");
         return -1;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM