• 【网络编程】——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
    ",
    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!
    ");
            }
        }
        else {
             perror("connect");
             return -1;
        }
    }
  • 相关阅读:
    《梦断代码》阅读笔记01
    linux c netcdf 安装
    Windows CE中的进程和线程
    VC做任务管理器涉及到的函数
    curl_easy_getinfo() -- 从 curl 句柄里获得附加信息
    libcurl programming
    动态内存申请函数选择(realloc、malloc 、alloca、 calloc)
    C++: byte和int的相互转化
    8位灰度图像BMP的保存
    BMP图像的结构及读写和灰度化
  • 原文地址:https://www.cnblogs.com/ngnetboy/p/5482857.html
Copyright © 2020-2023  润新知