CentOS 上的“信号”功能:意外行为
Posted
技术标签:
【中文标题】CentOS 上的“信号”功能:意外行为【英文标题】:`signal` function on CentOS: unexpected behavior 【发布时间】:2014-08-13 07:03:55 【问题描述】:我需要在 CentOS 应用程序上禁用SIGPIPE
,因为当我的应用程序在不稳定的 Internet 连接下工作时,这个信号会使我的应用程序崩溃。
我在main
函数中使用以下代码:
signal(SIGPIPE, SIG_IGN);
但是,程序仍然会因SIGPIPE
而崩溃。是什么原因?我必须在每个线程上调用这个函数,还是调用main
函数就足够了,程序会全局忽略SIGPIPE
?如果不需要在每个线程上调用它,为什么SIGPIPE
应该忽略信号仍然会使程序崩溃?
【问题讨论】:
在多线程应用程序中,您不应使用 signal 而应使用 sigaction。阅读here了解更多详情 【参考方案1】:这是一个代码示例,可让您在 linux 上设置自己的信号处理程序,捕获 SIGPIPE 并用它做一些事情。
#include <signal.h>
#include <unistd.h>
#include <cerrno>
#include <system_error>
#include <iostream>
static sigset_t theMask;
static int count = 0;
static void
signalWrapper(
int theSignalNumber,
siginfo_t* theSignalDescription,
void* theUserContext)
// Do something here as reaction to you SIGPIPE
// This is better way to react on such things
std::cout << "Got signal " << theSignalNumber << std::endl;
// Reinstall handler
struct ::sigaction sa;
sa.sa_sigaction = &signalWrapper;
sa.sa_mask = theMask;
sa.sa_flags = SA_SIGINFO;
try
if (::sigaction(theSignalNumber, &sa, NULL) == -1)
throw std::error_code(errno, std::system_category());
catch (const std::error_code& ec)
std::cerr << ec << std::endl;
count++;
void
setupSignalHandlers()
struct ::sigaction sa;
// Prepare mask
sigemptyset(&theMask);
sigaddset(&theMask, SIGPIPE);
// Add some more if you need it to process
sa.sa_mask = theMask;
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = &signalWrapper;
// Perform setup
try
if (::sigaction(SIGPIPE, &sa, NULL) == -1)
throw std::error_code(errno, std::system_category());
catch (const std::error_code& ec)
std::cerr << ec << std::endl;
int
main()
std::cout << "Set handler!" << std::endl;
setupSignalHandlers();
std::cout << "Emit 5 SIGPIPE signals" << std::endl;
while (count < 5)
kill(getpid(), SIGPIPE);
usleep(100);
return 0;
和输出:
Set handler!
Emit 5 SIGPIPE signals
Got signal 13
Got signal 13
Got signal 13
Got signal 13
Got signal 13
我提供信号处理程序,因为处理破坏应用程序的信号比忽略它更正确。也许您需要重新建立连接或做一些其他事情。
【讨论】:
【参考方案2】:根据 Signal(2) 的手册页,“未指定多线程进程中 signal() 的影响。”您可以尝试确保在创建任何其他线程之前在主线程中调用 signal(),但不能保证它可以正常工作。
无论如何,signal() 已被弃用,所以我建议切换到 sigaction()。我一直在多线程应用程序中使用它,没有任何问题。
【讨论】:
以上是关于CentOS 上的“信号”功能:意外行为的主要内容,如果未能解决你的问题,请参考以下文章
OS X 上的奇数/错误 sem_getvalue 信号量行为