最近在公司項目中忽然報錯以下 「connect: Interrupted system call」, 通過查找代碼發現是在建立 socket 中執行了 connect 函數失敗致使。上網查閱資料發現這是 信號中斷EINTR 與 慢系統調用 的問題。html
慢系統調用:可能永遠阻塞的系統調用。編程
EINTR說明:若是進程在一個慢系統調用(slow system call)中阻塞時,當捕獲到某個信號且相應信號處理函數返回時,這個系統調用被中斷,調用返回錯誤,設置errno爲EINTR(相應的錯誤描述爲「Interrupted system call」)。socket
在博客 http://blog.csdn.net/benkaoya/article/details/17262053 信號中斷 與 慢系統調用 有詳細介紹。函數
那麼針對 EINTR 錯誤應該如何處理,或者如何規避這類問題。 建議查看此連接 http://www.madore.org/~david/computers/connect-intr.htmlspa
如下給出一些經常使用的處理方法:.net
◆ 人爲重啓被中斷的系統調用code
◆ 安裝信號時設置 SA_RESTART屬性(該方法對有的系統調用無效)htm
◆ 忽略信號(讓系統不產生信號中斷)blog
人爲當碰到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; } }