CentOS上的`signal`功能:意外行为

时间:2014-08-13 07:03:55

标签: c++ multithreading sockets signals signal-processing

我需要在CentOS应用程序上禁用SIGPIPE,因为当它与不稳定的Internet连接一起工作时,此信号会崩溃我的应用程序。 我在main函数中使用以下代码:

signal(SIGPIPE, SIG_IGN);

但是,程序仍然与SIGPIPE崩溃。是什么原因?我是否要在每个线程上调用此函数,或者只需调用main函数,程序将全局忽略SIGPIPE?如果不需要在每个线程上调用,为什么SIGPIPE如果忽略该信号仍会导致程序崩溃?

2 个答案:

答案 0 :(得分: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

我提供信号处理程序,因为处理打破你的应用程序的信号比忽略它更正确。也许你需要重新建立联系或做其他事情。

答案 1 :(得分:1)

根据Signal(2)的手册页,“未指定多线程进程中信号()的影响。”在创建任何其他线程之前,您可能会尝试确保在主线程中调用signal(),但不能保证它能够正常工作。

在任何情况下都不推荐使用signal(),所以我建议切换到sigaction()。我一直在多线程应用程序中使用它而没有任何问题。