zoukankan      html  css  js  c++  java
  • Linux SIGPIPE信号产生原因与解决方法

    产生SIGPIPE的原因

    SIGPIPE信号产生的原因:

    当服务器close一个连接时,若client端接着发数据。根据TCP协议的规定,会收到一个RST响应,client再往这个服务器发送数据时,系统会发出一个SIGPIPE信号给进程,告诉进程这个连接已经断开了,不要再写了。

    又或者当一个进程向某个已经收到RST的socket执行写操作时,内核向该进程发送一个SIGPIPE信号。该信号的缺省操作是终止进程,因此进程必须捕获它以免不情愿的被终止

    TCP的全双工信道其实是两条单工信道,client端调用close的时候,虽然本意是关闭两条信道,但是其实只能关闭它发送的那一条单工信道,还是可以接受数据,server端还是可以发送数据,并不知道client端已经完全关闭了。

    以下为引用:
    ”’对一个已经收到FIN包的socket调用read方法, 如果接收缓冲已空, 则返回0, 这就是常说的表示连接关闭. 但第一次对其调用write方法时, 如果发送缓冲没问题, 会返回正确写入(发送). 但发送的报文会导致对端发送RST报文, 因为对端的socket已经调用了close, 完全关闭, 既不发送, 也不接收数据. 所以, 第二次调用write方法(假设在收到RST之后), 会生成SIGPIPE信号, 导致进程退出.”’

    解决方法

    Linux 系统为大部分信号定义了缺省处理方法,当信号的缺省处理方法不满足需求时,可通过 sigaction()函数进行改变。

    如:signal(SIGPIPE, SIG_IGN);
    这时SIGPIPE交给了系统处理。

    服务器采用了fork的话,要收集垃圾进程,防止僵尸进程的产生,可以这样处理:

    signal(SIGCHLD,SIG_IGN);

    交给系统init去回收。
    这里子进程就不会产生僵尸进程了。

    在linux下写socket的程序的时候,如果尝试send到一个disconnected socket上,就会让底层抛出一个SIGPIPE信号。
    这个信号的缺省处理方法是退出进程,大多数时候这都不是我们期望的。因此我们需要重载这个信号的处理方法。调用以下代码,即可安全的屏蔽SIGPIPE:

    struct sigaction sa;
    sa.sa_handler = SIG_IGN;
    sigaction( SIGPIPE, &sa, 0 );

    signal设置的信号句柄只能起一次作用,信号被捕获一次后,信号句柄就会被还原成默认值了。
    sigaction设置的信号句柄,可以一直有效,值到你再次改变它的设置。

    struct sigaction action;
    action.sa_handler = handle_pipe;
    sigemptyset(&action.sa_mask);
    action.sa_flags = 0;
    sigaction(SIGPIPE, &action, NULL);
    void handle_pipe(int sig)
    {
    //不做任何处理即可
    }
  • 相关阅读:
    CentOS7配置本地yum源和在线yum源
    Centos7中安装samba服务器
    phpmydmain登录问题
    java实现简单的加法器
    我的偶像 凯文 米特尼克 简介
    安全好的地方分享
    a标签
    Vmware虚拟机 的工作模式
    java面板
    java的套接字实现远程连接
  • 原文地址:https://www.cnblogs.com/god-of-death/p/14021556.html
Copyright © 2011-2022 走看看