【网络编程】——connect函数碰见EINTR的处理

  最近在公司项目中忽然报错以下 “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;
    }
}
相关文章
相关标签/搜索