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)
    {
    //不做任何处理即可
    }
  • 相关阅读:
    随笔2
    随笔
    关于updateElement接口
    随笔1
    本地访问正常,服务器访问乱码 记录
    Redis (error) NOAUTH Authentication required.解决方法
    tomcat启动很慢 停留在 At least one JAR was scanned for TLDs yet contained no TLDs.
    微信公众号消息回复
    微信公众号 报token验证失败
    idea中web.xml报错 Servlet should have a mapping
  • 原文地址:https://www.cnblogs.com/god-of-death/p/14021556.html
Copyright © 2011-2022 走看看