SIGPIPE信号详解及
SIGPIPE信号详解
当服务器close一个连接时,若client端接着发数据。根据TCP协议的规定,会收到一个RST响应,client再往这个服务器发送数据时,系统会发出一个SIGPIPE信号给进程,告诉进程这个连接已经断开了,不要再写了。
我写了一个服务器程序,在Linux下测试,然后用C++写了客户端用千万级别数量的短链接进行压力测试. 但是服务器总是莫名退出,没有core文件.
最后问题确定为, 对一个对端已经关闭的socket调用两次write, 第二次将会生成SIGPIPE信号, 该信号默认结束进程.
具体的分析可以结合TCP的"四次握手"关闭. TCP是全双工的信道, 可以看作两条单工信道, TCP连接两端的两个端点各负责一条. 当对端调用close时, 虽然本意是关闭整个两条信道, 但本端只是收到FIN包. 按照TCP协议的语义, 表示对端只是关闭了其所负责的那一条单工信道, 仍然可以继续接收数据. 也就是说, 因为TCP协议的限制, 一个端点无法获知对端的socket是调用了close还是shutdown.
对一个已经收到FIN包的socket调用read方法, 如果接收缓冲已空, 则返回0, 这就是常说的表示连接关闭. 但第一次对其调用write方法时, 如果发送缓冲没问题, 会返回正确写入(发送). 但发送的报文会导致对端发送RST报文, 因为对端的socket已经调用了close, 完全关闭, 既不发送, 也不接收数据. 所以, 第二次调用write方法(假设在收到RST之后), 会生成SIGPIPE信号, 导致进程退出.
为了避免进程退出, 可以捕获SIGPIPE信号, 或者忽略它, 给它设置SIG_IGN信号处理函数:
signal(SIGPIPE, SIG_IGN);
这样, 第二次调用write方法时, 会返回-1, 同时errno置为SIGPIPE. 程序便能知道对端已经关闭.
在linux下写socket的程序的时候,如果尝试send到一个disconnected socket上,就会让底层抛出一个SIGPIPE信号。
这个信号的缺省处理方法是退出进程,大多数时候这都不是我们期望的。因此我们需要重载这个信号的处理方法。调用以下代码,即可安全的屏蔽SIGPIPE:
signal (SIGPIPE, SIG_IGN);
我的程序产生这个信号的原因是:
client端通过 pipe 发送信息到server端后,就关闭client端, 这时server端,返回信息给 client 端时就产生Broken pipe 信号了,服务器就会被系统结束了。
对于产生信号,我们可以在产生信号前利用方法 signal(int signum, sighandler_t handler) 设置信号的处理。如果没有调用此方法,系统就会调用默认处理方法:中止程序,显示提示信息(就是我们经常遇到的问题)。我们可以调用系统的处理方法,也可以自定义处理方法。
系统里边定义了三种处理方法:
(1)SIG_DFL信号专用的默认动作:
(a)如果默认动作是暂停线程,则该线程的执行被暂时挂起。当线程暂停期间,发送给线程的任何附加信号都不交付,直到该线程开始执行,但是SIGKILL除外。
(b)把挂起信号的信号动作设置成SIG_DFL,且其默认动作是忽略信号 (SIGCHLD)。
(2)SIG_IGN忽略信号
(a)该信号的交付对线程没有影响
(b)系统不允许把SIGKILL或SIGTOP信号的动作设置为SIG_DFL
3)SIG_ERR
项目中我调用了signal(SIGPIPE, SIG_IGN), 这样产生 SIGPIPE 信号时就不会中止程序,直接把这个信号忽略掉。
iOS端内处理sigpipe
当使用 socket 进行网络连接时,如果连接中断,在默认情况下,你的 process 会收到一个 SIGPIPE
信号。如果你没有处理这个信号,app 会直接 crash!!!
有两种方法可以解决这个问题,任选其一:
- 在全局范围内忽略这个信号
signal(SIGPIPE, SIG_IGN);
需要注意的是,这个方法是全局通用的,所有的 SIGPIPE
信号都将被忽略
- 在一开始的时候设置 socket 不要发送
SIGPIPE
信号
/// sock 就是设置不发送 `SIGPIPE` 信号的 socket 变量
int value = 1;
setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value));
附上 APPLE 原文(ref1):
Use POSIX sockets efficiently (if at all). If you are using POSIX sockets directly:
- Handle or disable
SIGPIPE
.
When a connection closes, by default, your process receives a
SIGPIPE
signal. If your program does not handle or ignore this signal, your program will quit immediately. You can handle this in one of two ways:
- Ignore the signal globally with the following line of code:
signal(SIGPIPE, SIG_IGN);
- Tell the socket not to send the signal in the first place with the following lines of code (substituting the variable containing your socket in place of sock):
int value = 1; setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value));
For maximum compatibility, you should set this flag on each incoming socket immediately after calling accept in addition to setting the flag on the listening socket itself.
SIGPIPE信号详解及相关推荐
- SIGPIPE信号详解
SIGPIPE信号详解 当服务器close一个连接时,若client端接着发数据.根据TCP协议的规定,会收到一个RST响应,client再往这个服务器发送数据时,系统会发出一个SIGPIPE信号给进 ...
- signal信号详解
signal信号详解本文引用其它网站. 信号机制是进程之间相互传递消息的一种方法,信号全称为软中断信号,也有人称作软中断.从它的命名可以看出,它的实质和使用很象中断.所以,信号可以说是进程控制的一部分 ...
- Linux信号详解:signal与sigaction函数【2】
我们已经讨论了Linux操作系统中"信号"."中断"."僵尸进程"'等重要概念.结合C语言中的setjmp.longjump.sigsetj ...
- 轮毂电机光电增量编码器的ABZ信号详解
轮毂电机ABZ信号详解. 轮毂电机的定位使用了霍尔信号和光电增量编码器,1024线的.也就意味着,轮子转一圈,A信号和B信号各有1024个高电平和低电平. 实际应用中,我们将A/B信号的上升沿和下降沿 ...
- ASUS笔记本电路信号详解
ASUS笔记本电路信号详解 BATSEL_2P#:EC通过SM总线得知电池电量信息后,发出BATSEL_2P#信号,给充放电芯片,控制充电电流(控制ICTL). BATSEL_3S#:EC通过SM总 ...
- 【Linux信号专题】五、SIGCHLD信号详解
欢迎关注博主 Mindtechnist 或加入[Linux C/C++/Python社区]一起探讨和分享Linux C/C++/Python/Shell编程.机器人技术.机器学习.机器视觉.嵌入式AI ...
- 《PyQt5高级编程实战》自定义信号详解
自定义信号详解 1. 创建自定义信号 2. 让自定义信号携带值 3. 自定义信号的重载版本 4. 窗口间通信 5. 线程间通信 PyQt5中各个控件自带的信号已经能够让我们完成许多需求,但是如果想要更 ...
- Linux系统的信号详解
一.信号类型 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) ...
- 【Linux】第八讲:Linux进程信号详解(一)_ 认识信号 | 产生信号
「前言」文章是关于Linux进程信号方面的知识,本文的内容是Linux进程信号第一讲,讲解会比较细,下面开始! 「归属专栏」Linux系统编程 「笔者」枫叶先生(fy) 「座右铭」前行路上修真我 「枫 ...
最新文章
- Python并发编程实例教程
- 如何在python中创建列表副本,在Python中切片列表而不生成副本
- 中小型商业银行的软件安全测试之道
- NLP-基础知识-003(词性标注)
- c++ 分析core文件 在os x
- swagger3 设置值可以为空_【Swagger2】【3】API注解详解,以及注解常用参数配置
- 探寻浏览器渲染的秘密
- Windows 11 快速体验:开始菜单居中,全系圆角设计!
- JS中ptototype和__proto__的关系
- ubuntu部署tomcat
- 【英语学习】【Level 07】U06 First Time L4 Lost in Shanghai
- CS48 D BIT
- 双系统重装windows后修复UBUNTU的GRUB
- C++ / vs 如何生成自己的静态库(lib)文件
- Funcode实现打飞虫1
- VMWare虚拟机Linux系统忘记登录密码
- 简单人物画像_简易人物画像图
- 建筑设计的未来是什么?| 建筑 · 人工智能专栏
- 网络安全学习--002--windows基础知识
- 龙芯linux内核空间内存划分,最强龙芯+最新内核+最大内存
热门文章
- Pg处理MIMIC数据
- python实现签名RSA算法
- 在相同CDB下进行unplug,plug PDB的操作。(plug or unplug a pdb using same cdb)
- 2021年电工(初级)答案解析及电工(初级)作业考试题库
- 美亚柏科:与阿里就公安云计算签合作协议
- php生成随机数永不重复,PHP生成不重复随机数的方法汇总
- 机器学习稀疏矩阵简介(附Python代码)
- QT自定义安装包制作原理
- http://itunes.apple.com/lookup?id=获取不到版本
- Python处理图片