1 现象:问题描述
OIA运行一段时间,网络异常后,偶尔会自动终止且没有core文件。
2 关键过程:根本原因分析
由于程序为后台常驻进程,没有正常退出点。因此首先分析异常信号处理,由于OIA使用了SOCKET进行通信,帮助分析的同事指出需要对管道破裂的信号进行处理。
当一个进程向已经接收到了RST的SOCKET进行写操作时,内核则产生SIGPIPE信号。向一个没有被打开用来读的管道或FIFO中写数据也会产生一个SIGPIPE信号。信号是软件中断,比较重要的应用程序需要处理信号,信号提供了一种处理异步消息的方法。
OIA没有对SIGPIPE信号进行处理,而系统对SIGPIPE的默认处理方式为终止进程。使用gdb进行调试,模拟各种网络问题gdb可以跟踪到OIA在执行write调用时出现pipe broken。
3 结论:解决方案及效果
由于SIGPIPE信号的默认动作是终止,所以,这里需要处理此信号,防止程序终止。
使用signal函数处理时,第二个参数可以有三种取值
1) SIG_IGN,表示内核忽略此信号。
2) SIG_DFL,表示接到此信号后的动作是默认动作。
3) 接到此信号时要调用的函数的地址,当指向函数地址时,我们称此为捕捉此信号。
在main函数中增加对SIGPIPE信号的处理,忽略此信号,防止程序中断:
//原因:捕获该信号SIGPIPE信号,避免OIA进程终止。
signal(SIGPIPE, SIG_IGN);
4 经验总结:预防措施和规范建议
对于使用I/O操作频繁时,容易引入信号处理异常。为了防止程序退出(这种问题一般很难定位),对于这种异常,需要对信号进行处理。在使用Socket和管道的程序中,需要通过函数signal指定对信号SIGPIPE的处理,使用SIG_IGN(表示内核忽略此信号)作为默认的处理动作或程序自己实现处理动作,防止程序异常退出。关于网络异常引起的SIGPIPE详细解释,请参考《UNIX 网络编程 第一卷》 5.13 SIGPIPE 信号部分。
5 备注
6 考核点
对信号SIGPIPE的处理。
7 试题
1、 关于对信号SIGPIPE的处理,说法正确的是:C
A) socket操作不会引起SIGPIPE信号,没有必要关注信号SIGPIPE的处理。
B) 由于SIGPIPE的默认动作是忽略,所以没有必要关注信号SIGPIPE的处理。
C) 程序中在指定signal函数对信号SIGPIPE的处理时,应该使用SIG_IGN(表示内核忽略此信号)作为默认的处理动作,从而保证程序不会终止。
D) 程序中在指定signal函数对信号SIGPIPE的处理时,应该使用SIG_DFL (表示接到此信号后的动作是默认动作)作为默认的处理动作,从而保证程序不会终止。
阅读(562) | 评论(0) | 转发(0) |