CentOS上的' signal '函数:意外行为

`signal` function on CentOS: unexpected behavior

本文关键字:意外 signal 上的 CentOS 函数      更新时间:2023-10-16

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

signal(SIGPIPE, SIG_IGN);

然而,程序仍然崩溃与SIGPIPE。原因是什么?我是否需要在每个线程上调用这个函数,或者调用main函数就足够了,程序将全局忽略SIGPIPE ?如果它不需要在每个线程上调用,为什么SIGPIPE仍然崩溃程序,如果它应该忽略信号?

这是一个代码示例,可以让您在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

我提供信号处理程序,因为处理中断应用程序的信号比忽略它更正确。也许你需要重新建立连接或做一些其他的事情。

根据Signal(2)的手册页," Signal()在多线程进程中的效果是未指定的。"您可以尝试在创建任何其他线程之前在主线程中调用signal(),但不能保证它能工作。

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