关于SIGPIPE导致的程序退出

在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。
在Unix系统下,如果recv在等待协议接收数据时网络断开了,那么调用recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。

处理方法:
在初始化时调用signal(SIGPIPE,SIG_IGN) 忽略该信号(只需一次)
其时send或recv函数将返回-1,errno为EPIPE,可视情况关闭socket或其他处理

gdb:
gdb默认收到sigpipe时中断程序,可调用handle SIGPIPE nostop print

相关

(1)SIG_DFL信号专用的默认动作:
(a)如果默认动作是暂停线程,则该线程的执行被暂时挂起。当线程暂停期间,发送给线程的任何附加信号都不交付,直到该线程开始执行,但是SIGKILL除外。
(b)把挂起信号的信号动作设置成SIG_DFL,且其默认动作是忽略信号 (SIGCHLD)。

(2)SIG_IGN忽略信号
(a)该信号的交付对线程没有影响
(b)系统不允许把SIGKILL或SIGTOP信号的动作设置为SIG_DFL

(3)指向函数的指针--捕获信号
(a)信号一经交付,接收线程就在指定地址上执行信号捕获程序。在信号捕 获函数返回后,接受线程必须在被中断点恢复执行。
(b)用C语言函数调用的方法进入信号捕捉程序:
void func (signo)
int signo;
func( )是指定的信号捕捉函数,signo是正被交付信号的编码
(c)如果SIGFPE,SIGILL或SIGSEGV信号不是由C标准定义的kill( )或raise( )函数所生成,则从信号SIGFPE,SIGILL,SIGSEGV的信号捕获函数正常返回后线程的行为是未定义的。
(d)系统不允许线程捕获SIGKILL和SIGSTOP信号。
(e)如果线程为SIGCHLD信号建立信号捕获函数,而该线程有未被等待的以终止的子线程时,没有规定是否要生成SIGCHLD信号来指明那个子线程。

每一种信号都被OSKit给予了一个符号名,对于32位的i386平台而言,一个字32位,因而信号有32种。下面的表给出了常用的符号名、描述和它们的信号值。

符号名 信号值 描述 是否符合POSIX
SIGHUP 1 在控制终端上检测到挂断或控制线程死亡 是
SIGINT 2 交互注意信号 是
SIGQUIT 3 交互中止信号 是
SIGILL 4 检测到非法硬件的指令 是
SIGTRAP 5 从陷阱中回朔 否
SIGABRT 6 异常终止信号 是
SIGEMT 7 EMT 指令 否
SIGFPE 8 不正确的算术操作信号 是
SIGKILL 9 终止信号 是
SIGBUS 10 总线错误 否
SIGSEGV 11 检测到非法的内存调用 是
SIGSYS 12 系统call的错误参数 否
SIGPIPE 13 在无读者的管道上写 是
SIGALRM 14 报时信号 是
SIGTERM 15 终止信号 是
SIGURG 16 IO信道紧急信号 否
SIGSTOP 17 暂停信号 是
SIGTSTP 18 交互暂停信号 是
SIGCONT 19 如果暂停则继续 是
SIGCHLD 20 子线程终止或暂停 是
SIGTTIN 21 后台线程组一成员试图从控制终端上读出 是
SIGTTOU 22 后台线程组的成员试图写到控制终端上 是
SIGIO 23 允许I/O信号 否
SIGXCPU 24 超出CPU时限 否
SIGXFSZ 25 超出文件大小限制 否
SIGVTALRM 26 虚时间警报器 否
SIGPROF 27 侧面时间警报器 否
SIGWINCH 28 窗口大小的更改 否
SIGINFO 29 消息请求 否
SIGUSR1 30 保留作为用户自定义的信号1 是
SIGUSR2 31 保留作为用户自定义的信号 是 
注意:Linux 信号机制基本上是从Unix系统中继承过来的。早期Unix系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,因此,把那些建立在早期机制上的信号叫做"不可靠信号",信号值小于SIGRTMIN(Red hat 7.2中,SIGRTMIN=32,SIGRTMAX=63)的信号都是不可靠信号。这就是"不可靠信号"的来源。它的主要问题是:进程每次处理信号后,就将对信号的响应设置为默认动作。在某些情况下,将导致对信号的错误处理;因此,用户如果不希望这样的操作,那么就要在信号处理函数结尾再一次调用 signal(),重新安装该信号。

另外,我再做一些补充,产生RST响应以至于系统发出SIGPIPE信号,应该分为两种情况:

1. 客户端到服务端之间网络断掉,或者服务端断电等,物理连接断掉了,这种情况下客户端不会退出,send函数正常执行,不会感觉到自己出错。因为由于物理网络断开,服务端不会给客户端回应错误消息,没有RST响应,自然也不会产生SIGPIPE信号。但是当服务端再恢复正常的时候,对客户端send来的消息会产生RST响应,客户端就收到SIGPIPE信号了,程序退出,但是这时send函数是能够返回 -1的。可以进行异常处理。

2.客户端到服务端的网络能通,服务程序挂掉,客户端程序会马上退出,因为服务端能正常返回错误消息,客户端收到,SIGPIPE信号就产生了。不过我不确定此时服务端返回是的RST响应,抓包来看没有RST标志。水平有限,只写到这了。

原文出处(请点击)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值