linux 编程中忽略SIGPIPE信号
SIGPIPE
简单来说,就是客户端程序向服务器端程序发送了消息,然后关闭客户端,服务器端返回消息的时候就会收到内核给的SIGPIPE信号。
TCP的全双工信道其实是两条单工信道,client端调用close的时候,虽然本意是关闭两条信道,但是其实只能关闭它发送的那一条单工信道,还是可以接受数据,server端还是可以发送数据,并不知道client端已经完全关闭了。
以下为引用:
”’对一个已经收到FIN包的socket调用read方法, 如果接收缓冲已空, 则返回0, 这就是常说的表示连接关闭. 但第一次对其调用write方法时, 如果发送缓冲没问题, 会返回正确写入(发送). 但发送的报文会导致对端发送RST报文, 因为对端的socket已经调用了close, 完全关闭, 既不发送, 也不接收数据. 所以, 第二次调用write方法(假设在收到RST之后), 会生成SIGPIPE信号, 导致进程退出.”’
简单忽略SIGPIPE
struct sigaction action;
action.sa_handler = SIG_IGN;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
sigaction(SIGPIPE, &action, NULL);
sendBytes = send(Fd, Buff, readBytes, MSG_NOSIGNAL);
以下为一劳永逸,设置多个忽略的信号
/*****************************************************************************
* NAME: UpdateSignalHandling
*
* DESCRIPTION:
* this function sets up the signal handling and masking for the daemon
* process. the following is done here:
*
* o - change some default signal disposition with sigaction().
* o - block all signals. we will use sigwait() in a dedicated thread
* to process the signals we are interested in.
*
* the failures in this function are non-fatal. so we keep going after
* taking a note of the error code.
*
* INPUTS:
* NONE.
*
* RETURN:
* int.
*/
static
int
UpdateSignalHandling(
void
)
{
sigset_t sigset;
struct sigaction sa = { .sa_handler = SIG_IGN };
int status = 0;
if (sigfillset(&sa.sa_mask) == 0)
{
static int IGNORE_SIG[] = { SIGINT, SIGTERM, SIGCHLD, SIGHUP, SIGPIPE, SIGIO };
unsigned int i = 0;
for (i = 0; i < sizeof(IGNORE_SIG)/sizeof(IGNORE_SIG[0]); i++)
{
if (sigaction(IGNORE_SIG[i], &sa, NULL) != 0)
{
status = -errno;
}
}
}
else
{
status = -errno;
}
if (sigfillset(&sigset) == 0)
{
static int UNMASK_SIG[] = { SIGBUS, SIGFPE, SIGILL, SIGSEGV };
unsigned int i = 0;
int r = 0;
for (i = 0; i < sizeof(UNMASK_SIG)/sizeof(UNMASK_SIG[0]); i++)
{
(void)sigdelset(&sigset, UNMASK_SIG[i]);
}
/*
* per man page, the use of sigprocmask() is unspecified in MT process.
* use pthread_sigmask() instead.
*/
r = pthread_sigmask(SIG_BLOCK, &sigset, NULL);
if (r != 0)
{
status = -r;
}
}
else
{
status = -errno;
}
return status;
}