求助,如何正确屏蔽sigpipe 头文件信号

关于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
设置信号的处理。如果没有调用此方法,系统就会调用默认处理方法:中止程序,显示提示信息(就是我们经常遇到的问题)。我们可以调用系统的处理方法,也可以自定义处理方法。&
系统里边定义了三种处理方法:&
(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 - decwang - 博客园
随笔 - 145
今天下午,在IOS上调试TCP通用接口,发现总是出现SIGPIPE异常问题,一开始没想明白怎么回事,突然想起来,之前在MDO项目中LINUX下,是需要屏蔽SIGPIPE信号的,不然程序铁定崩溃。
上网搜了下,最土的办法,直接屏蔽SIGPIPE信号,次一点的,在SOCKET中用SO_NOSIGPIPE进行屏蔽。
写网络程序时候, 当向对方wrtie数据时候对方主动close了连接, 会产生SIGPIPE信号, 如果不对这个信号处理程序就会退出或者也可以说崩掉了, 所以一般简单处理就是忽略掉这个信号,
signal(SIGPIPE, SIG_IGN);
但是遇到一个诡异的问题, 用Xcode debug设备做并发测试的时候程序就会崩溃, 怎么都查不出来原因, 后来不用Xcode debug, 直接在设备运行App再进行压力测试就没问题了, 也就是说在Xcode debug的时候, 忽略SIGPIPE是不起作用的.
阅读(...) 评论()C语言中信号问题_百度知道
C语言中信号问题
if (signal(SIGTSTP;#include &can'
} return nlines,&quot.h&),\can'
offset = 0;alarm(0);/);}static void sig_term(int signo){clock ticks since system startup are %d;
p =n&quot,但是我不想它有输出,sig_alrm)==SIG_ERR)err_sys(&/&#47.h&
offset = nlines - 10;);printf(&
nlines = readlines(* The input lines are stored end-to-alarm(10),wallclock); i &)
*p = 'int wallclock=times(&timebuf),sig_int)==SIG_ERR)err_sys(&t catch SIGTERM&t catch SIGALRM&&#47.h&
while ((c = getchar()) ;n&don&#39,&can'
char *p;;t tick when outputprintf(& 10, lineptr[offset + i]). */;n& /restart}int main(){if (signal(SIGINT;#include & i++)
&#47, str )#define MAXLINES 1000char *lineptr[MAXLINES], MAXLINES),
for (i = 0; 10) {
printf(&startif (signal(SIGALRM:%s\;exit(0);= buffer + BUFFERSIZE) {
if (p &if (signal(SIGTERM,0); ,wallclock);sys/exit}static void sig_tstp(int signo){ #include &lt.\);0'n'error: only can print the last %d lines:%d\while(1) ,sig_term)==SIG_ERR)err_sys(& ;unistd, with
newlines conint wallclock=times(&timebuf);\alarm(10);#define err_sys( str ) printf(& /n&#include &;wait herereturn(0);#define BUFFERSIZE 1000 static void sig_int(int signo){\
*p = c,但是现在没有;
if (nlines &/ /
char buffer[BUFFERSIZE];
p++;clock ticks since system start are %d,sig_term)==SIG_ERR)err_sys(& }int readlines(char *lineptr[];fprintf(stderr.h&gt:%d\t catch SIGINT&;%s\error,can&#39!= EOF) {
if (c == 'n&quot.h&times++ ,fprintf(&#47, char *buffer,}static void sig_alrm(int signo){static int times=1;} 我想在接收sigterm时有我程序中的输出,\n&quot, times*10 ); nlines && i &lt, nlines); /Kill -15 却有输出, int maxlines) {
int c#include &n&tick,求大神改改程序;;t catch SIGTSTP&quot
程序需要在接收到sigterm后输出程序时间并退出程序,我这个好像没有输出吧?求各位大神再看看
提问者采纳
linux下可查&#47SIGTERM的值就是15见下表;include/usr/asm&#47
程序需要在接收到sigterm后输出程序时间并退出程序,我这个好像没有输出吧?
if (signal(SIGTERM,sig_term)==SIG_ERR) //这句是注册sig_termstatic void sig_term(int signo)
//这是sig_term的定义,其中有输出{int wallclock=times(&timebuf);fprintf(stderr,&clock ticks since system start are %d,\n&,wallclock);exit(0); //exit}
提问者评价
原来是这样,感谢!
来自团队:
其他类似问题
为您推荐:
其他2条回答
你的信号捕捉程序没问题,但是你没有搞清楚SIGTERM信号的值
那应该是什么啊?
信号是程序执行过程中出现的异常情况。它可能是由程序中的错误造成的,例如引用内存中的一个非法地址;或者是由程序数据中的错误造成的,例如浮点数被0除;或者是由外部事件引发的,例如用户按了Ctrl+Break键。
你可以利用标准库函数signal()指定要对这些异常情况采取的处理措施(实施处理措施的函数被称为“信号处理函数”)。signal()的原型为:
&signal.h&
void(*signal(int hum,void(*func)(int)))(int);
如果定义一个typedef,理解起来就容易一些了。下面给出的sigHandler_t类型是指向一个程序的指针,该函数有一个int类型的参数,并且返回一个void类型:
typedef void(*sigHandler_t)(int);
sigHandler_t signal(int num , sigHandler_t func);
signal()有两个参数,分别为int类...
c语言的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁}

我要回帖

更多关于 sigpipe一定要屏蔽么 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信