linux下多线程由于SIGPIPE退出进程的分析。

来源:互联网 发布:linux用kill进程的方法 编辑:程序博客网 时间:2024/06/08 08:42

起因

对于一个对端关闭了的socket进行两次写操作,第二次会产生一个SIGPIPE信号,该信号默认退出进程。
具体如何分析可以参见tcp四次挥手。
这里写图片描述
tcp协议是全双工的,这就可以看成是两条单工信道,单工信道是管道PIPE,在对端调用close后,对端将发送一个FIN标志给本端,在本端进行read返回0的话,就表示对端关闭了对端负责的一条管道,但是本端这一条管道还可以进行通信,(引申一下tcp的限制,一个端点无法获知对端已经完全关闭,因为是用两条单工模拟的,每一条都可以向对方发送字节流。)。当本端第一次调用write的时候,没问题,对端接收后,立马发送一个RST标志给本端,告诉本端,对端已经完全关闭,即第二次的write会引起SIGPIPE的信号。

解决方案

忽略SIGPIPE
1. 方案一:

struct sigaction sa;
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
if((sigemptyset(&sa.sa_mask) == -1) || sigaction(SIG_PIPE, &sa, 0) == -1)
{
perror("SIGPIPE");
exit(EXIT_FAILURE)
}

这种方法对于进程可以忽略SIGPIPE。
但是POSIX的线程,对信号的捕获是逐条线程进行的,所以引出了下面的解决方案。
2. 方案二:

sigset_t signal_mask;
sigemptyset(&signal_mask);
sigaddset(&signal_mask, SIG_PIPE);
if(pthread_sigmask(SIG_BLOCK, &signal_mask, NULL) == -1)
perror("SIG_PIPE");

这样就能屏蔽掉线程中的SIG_PIPE。

0 0
原创粉丝点击